Remove directory part from filenames in function declarations.
[bpt/emacs.git] / lisp / progmodes / prolog.el
CommitLineData
6594deb0
ER
1;;; prolog.el --- major mode for editing and running Prolog under Emacs
2
d7a0267c 3;; Copyright (C) 1986, 1987, 2001, 2002, 2003, 2004, 2005, 2006, 2007
034babe1 4;; Free Software Foundation, Inc.
9750e079 5
0acdb863 6;; Author: Masanobu UMEDA <umerin@mse.kyutech.ac.jp>
d7b4d18f 7;; Keywords: languages
e5167999 8
d8025917 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
1a484753 13;; the Free Software Foundation; either version 3, or (at your option)
d8025917 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
b578f267 22;; along with GNU Emacs; see the file COPYING. If not, write to the
3a35cf56
LK
23;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
24;; Boston, MA 02110-1301, USA.
d8025917 25
edbd2f74
ER
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
f614a1ae 30;; Prolog interpreter process. Font locking is tuned towards GNU Prolog.
edbd2f74 31
e5167999
ER
32;;; Code:
33
3cd79f62
DN
34(defvar comint-prompt-regexp)
35(defvar comint-process-echoes)
4e186ad5 36
c5292bc8 37(defgroup prolog nil
73efac49 38 "Major mode for editing and running Prolog under Emacs."
8ec3bce0 39 :link '(custom-group-link :tag "Font Lock Faces group" font-lock-faces)
c5292bc8
RS
40 :group 'languages)
41
f614a1ae 42
6cfd4f3a 43(defcustom prolog-program-name
d364dee6 44 (let ((names '("prolog" "gprolog" "swipl")))
6cfd4f3a
SM
45 (while (and names
46 (not (executable-find (car names))))
47 (setq names (cdr names)))
48 (or (car names) "prolog"))
d364dee6 49 "Program name for invoking an inferior Prolog with `run-prolog'."
c5292bc8
RS
50 :type 'string
51 :group 'prolog)
d8025917 52
c5292bc8 53(defcustom prolog-consult-string "reconsult(user).\n"
d364dee6 54 "(Re)Consult mode (for C-Prolog and Quintus Prolog). "
c5292bc8
RS
55 :type 'string
56 :group 'prolog)
d8025917 57
c5292bc8 58(defcustom prolog-compile-string "compile(user).\n"
d364dee6 59 "Compile mode (for Quintus Prolog)."
c5292bc8
RS
60 :type 'string
61 :group 'prolog)
d8025917 62
c5292bc8 63(defcustom prolog-eof-string "end_of_file.\n"
d364dee6 64 "String that represents end of file for Prolog.
c6c5714e 65When nil, send actual operating system end of file."
c5292bc8
RS
66 :type 'string
67 :group 'prolog)
d8025917 68
c5292bc8
RS
69(defcustom prolog-indent-width 4
70 "Level of indentation in Prolog buffers."
71 :type 'integer
72 :group 'prolog)
d8025917 73
f614a1ae
TTN
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
6cfd4f3a 84(defvar prolog-mode-syntax-table
d8025917 85 (let ((table (make-syntax-table)))
86 (modify-syntax-entry ?_ "w" table)
87 (modify-syntax-entry ?\\ "\\" table)
f614a1ae
TTN
88 (modify-syntax-entry ?/ ". 14" table)
89 (modify-syntax-entry ?* ". 23" table)
d8025917 90 (modify-syntax-entry ?+ "." table)
91 (modify-syntax-entry ?- "." table)
92 (modify-syntax-entry ?= "." table)
93 (modify-syntax-entry ?% "<" table)
673f4fc6 94 (modify-syntax-entry ?\n ">" table)
d8025917 95 (modify-syntax-entry ?< "." table)
96 (modify-syntax-entry ?> "." table)
97 (modify-syntax-entry ?\' "\"" table)
6cfd4f3a 98 table))
d8025917 99
6cfd4f3a 100(defvar prolog-mode-abbrev-table nil)
d8025917 101(define-abbrev-table 'prolog-mode-abbrev-table ())
102
103(defun prolog-mode-variables ()
d8025917 104 (make-local-variable 'paragraph-separate)
6cfd4f3a 105 (setq paragraph-separate (concat "%%\\|$\\|" page-delimiter)) ;'%%..'
d8025917 106 (make-local-variable 'paragraph-ignore-fill-prefix)
107 (setq paragraph-ignore-fill-prefix t)
2c239c80 108 (make-local-variable 'imenu-generic-expression)
d8059b03 109 (setq imenu-generic-expression '((nil "^\\sw+" 0)))
d8025917 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)
6cfd4f3a
SM
115 (setq comment-start-skip "\\(?:%+\\|/\\*+\\)[ \t]*")
116 (make-local-variable 'comment-end-skip)
117 (setq comment-end-skip "[ \t]*\\(\n\\|\\*+/\\)")
d8025917 118 (make-local-variable 'comment-column)
6cfd4f3a 119 (setq comment-column 48))
d8025917 120
6cfd4f3a
SM
121(defvar prolog-mode-map
122 (let ((map (make-sparse-keymap)))
123 (define-key map "\e\C-x" 'prolog-consult-region)
d364dee6
SM
124 (define-key map "\C-c\C-l" 'inferior-prolog-load-file)
125 (define-key map "\C-c\C-z" 'switch-to-prolog)
6cfd4f3a 126 map))
d364dee6
SM
127
128(easy-menu-define prolog-mode-menu prolog-mode-map "Menu for Prolog mode."
129 ;; Mostly copied from scheme-mode's menu.
130 ;; Not tremendously useful, but it's a start.
131 '("Prolog"
132 ["Indent line" indent-according-to-mode t]
133 ["Indent region" indent-region t]
134 ["Comment region" comment-region t]
135 ["Uncomment region" uncomment-region t]
136 "--"
137 ["Run interactive Prolog session" run-prolog t]
138 ))
d8025917 139
f9f9507e 140;;;###autoload
d8025917 141(defun prolog-mode ()
142 "Major mode for editing Prolog code for Prologs.
143Blank lines and `%%...' separate paragraphs. `%'s start comments.
144Commands:
145\\{prolog-mode-map}
573f9b32 146Entry to this mode calls the value of `prolog-mode-hook'
d8025917 147if that value is non-nil."
148 (interactive)
149 (kill-all-local-variables)
150 (use-local-map prolog-mode-map)
6cfd4f3a 151 (set-syntax-table prolog-mode-syntax-table)
d8025917 152 (setq major-mode 'prolog-mode)
153 (setq mode-name "Prolog")
154 (prolog-mode-variables)
d364dee6 155 (set (make-local-variable 'comment-add) 1)
f614a1ae
TTN
156 ;; font lock
157 (setq font-lock-defaults '(prolog-font-lock-keywords
158 nil nil nil
159 beginning-of-line))
6cfd4f3a 160 (run-mode-hooks 'prolog-mode-hook))
d8025917 161
d364dee6 162(defun prolog-indent-line ()
d8025917 163 "Indent current line as Prolog code.
164With argument, indent any additional lines of the same clause
165rigidly along with this one (not yet)."
166 (interactive "p")
167 (let ((indent (prolog-indent-level))
d364dee6 168 (pos (- (point-max) (point))))
d8025917 169 (beginning-of-line)
d364dee6 170 (indent-line-to indent)
d8025917 171 (if (> (- (point-max) pos) (point))
d364dee6 172 (goto-char (- (point-max) pos)))))
d8025917 173
174(defun prolog-indent-level ()
c6c5714e 175 "Compute Prolog indentation level."
d8025917 176 (save-excursion
177 (beginning-of-line)
178 (skip-chars-forward " \t")
179 (cond
180 ((looking-at "%%%") 0) ;Large comment starts
181 ((looking-at "%[^%]") comment-column) ;Small comment starts
182 ((bobp) 0) ;Beginning of buffer
183 (t
184 (let ((empty t) ind more less)
185 (if (looking-at ")")
186 (setq less t) ;Find close
187 (setq less nil))
188 ;; See previous indentation
189 (while empty
190 (forward-line -1)
191 (beginning-of-line)
192 (if (bobp)
193 (setq empty nil)
194 (skip-chars-forward " \t")
195 (if (not (or (looking-at "%[^%]") (looking-at "\n")))
196 (setq empty nil))))
197 (if (bobp)
198 (setq ind 0) ;Beginning of buffer
199 (setq ind (current-column))) ;Beginning of clause
200 ;; See its beginning
201 (if (looking-at "%%[^%]")
202 ind
203 ;; Real prolog code
204 (if (looking-at "(")
205 (setq more t) ;Find open
206 (setq more nil))
207 ;; See its tail
208 (end-of-prolog-clause)
209 (or (bobp) (forward-char -1))
210 (cond ((looking-at "[,(;>]")
211 (if (and more (looking-at "[^,]"))
212 (+ ind prolog-indent-width) ;More indentation
213 (max tab-width ind))) ;Same indentation
214 ((looking-at "-") tab-width) ;TAB
215 ((or less (looking-at "[^.]"))
216 (max (- ind prolog-indent-width) 0)) ;Less indentation
217 (t 0)) ;No indentation
218 )))
219 )))
220
221(defun end-of-prolog-clause ()
222 "Go to end of clause in this line."
223 (beginning-of-line 1)
224 (let* ((eolpos (save-excursion (end-of-line) (point))))
225 (if (re-search-forward comment-start-skip eolpos 'move)
226 (goto-char (match-beginning 0)))
227 (skip-chars-backward " \t")))
d8025917 228\f
229;;;
230;;; Inferior prolog mode
231;;;
6cfd4f3a
SM
232(defvar inferior-prolog-mode-map
233 (let ((map (make-sparse-keymap)))
234 ;; This map will inherit from `comint-mode-map' when entering
235 ;; inferior-prolog-mode.
23f2d048
SM
236 (define-key map [remap self-insert-command]
237 'inferior-prolog-self-insert-command)
6cfd4f3a
SM
238 map))
239
240(defvar inferior-prolog-mode-syntax-table prolog-mode-syntax-table)
241(defvar inferior-prolog-mode-abbrev-table prolog-mode-abbrev-table)
d8025917 242
5cec3056
GM
243(declare-function comint-mode "comint")
244(declare-function comint-send-string "comint" (process string))
245(declare-function comint-send-region "comint" (process start end))
246(declare-function comint-send-eof "comint" ())
153ef845 247
6cfd4f3a 248(define-derived-mode inferior-prolog-mode comint-mode "Inferior Prolog"
d8025917 249 "Major mode for interacting with an inferior Prolog process.
250
251The following commands are available:
252\\{inferior-prolog-mode-map}
253
573f9b32
RS
254Entry to this mode calls the value of `prolog-mode-hook' with no arguments,
255if that value is non-nil. Likewise with the value of `comint-mode-hook'.
256`prolog-mode-hook' is called after `comint-mode-hook'.
d8025917 257
c647adda
JB
258You can send text to the inferior Prolog from other buffers using the commands
259`process-send-region', `process-send-string' and \\[prolog-consult-region].
d8025917 260
261Commands:
262Tab indents for Prolog; with argument, shifts rest
263 of expression rigidly with the current line.
573f9b32
RS
264Paragraphs are separated only by blank lines and '%%'.
265'%'s start comments.
d8025917 266
267Return at end of buffer sends line as input.
268Return not at end copies rest of line to end and sends it.
269\\[comint-kill-input] and \\[backward-kill-word] are kill commands, imitating normal Unix input editing.
270\\[comint-interrupt-subjob] interrupts the shell or its current subjob if any.
271\\[comint-stop-subjob] stops. \\[comint-quit-subjob] sends quit signal."
6cfd4f3a
SM
272 (setq comint-prompt-regexp "^| [ ?][- ] *")
273 (prolog-mode-variables))
d8025917 274
d364dee6
SM
275(defvar inferior-prolog-buffer nil)
276
7caf6803
DN
277(defvar inferior-prolog-flavor 'unknown
278 "Either a symbol or a buffer position offset by one.
279If a buffer position, the flavor has not been determined yet and
280it is expected that the process's output has been or will
281be inserted at that position plus one.")
282
d364dee6
SM
283(defun inferior-prolog-run (&optional name)
284 (with-current-buffer (make-comint "prolog" (or name prolog-program-name))
285 (inferior-prolog-mode)
286 (setq-default inferior-prolog-buffer (current-buffer))
287 (make-local-variable 'inferior-prolog-buffer)
288 (when (and name (not (equal name prolog-program-name)))
289 (set (make-local-variable 'prolog-program-name) name))
290 (set (make-local-variable 'inferior-prolog-flavor)
291 ;; Force re-detection.
292 (let* ((proc (get-buffer-process (current-buffer)))
293 (pmark (and proc (marker-position (process-mark proc)))))
294 (cond
295 ((null pmark) (1- (point-min)))
296 ;; The use of insert-before-markers in comint.el together with
297 ;; the potential use of comint-truncate-buffer in the output
298 ;; filter, means that it's difficult to reliably keep track of
299 ;; the buffer position where the process's output started.
300 ;; If possible we use a marker at "start - 1", so that
301 ;; insert-before-marker at `start' won't shift it. And if not,
302 ;; we fall back on using a plain integer.
303 ((> pmark (point-min)) (copy-marker (1- pmark)))
304 (t (1- pmark)))))
305 (add-hook 'comint-output-filter-functions
306 'inferior-prolog-guess-flavor nil t)))
307
308(defun inferior-prolog-process (&optional dontstart)
309 (or (and (buffer-live-p inferior-prolog-buffer)
310 (get-buffer-process inferior-prolog-buffer))
311 (unless dontstart
312 (inferior-prolog-run)
313 ;; Try again.
314 (inferior-prolog-process))))
315
23f2d048
SM
316(defun inferior-prolog-guess-flavor (&optional ignored)
317 (save-excursion
318 (goto-char (1+ inferior-prolog-flavor))
319 (setq inferior-prolog-flavor
320 (cond
321 ((looking-at "GNU Prolog") 'gnu)
322 ((looking-at "Welcome to SWI-Prolog") 'swi)
323 ((looking-at ".*\n") 'unknown) ;There's at least one line.
324 (t inferior-prolog-flavor))))
325 (when (symbolp inferior-prolog-flavor)
326 (remove-hook 'comint-output-filter-functions
327 'inferior-prolog-guess-flavor t)
328 (if (eq inferior-prolog-flavor 'gnu)
329 (set (make-local-variable 'comint-process-echoes) t))))
330
f9f9507e 331;;;###autoload
d364dee6
SM
332(defalias 'run-prolog 'switch-to-prolog)
333;;;###autoload
334(defun switch-to-prolog (&optional name)
335 "Run an inferior Prolog process, input and output via buffer *prolog*.
336With prefix argument \\[universal-prefix], prompt for the program to use."
337 (interactive
338 (list (when current-prefix-arg
339 (let ((proc (inferior-prolog-process 'dontstart)))
340 (if proc
341 (if (yes-or-no-p "Kill current process before starting new one? ")
342 (kill-process proc)
343 (error "Abort")))
344 (read-string "Run Prolog: " prolog-program-name)))))
345 (unless (inferior-prolog-process 'dontstart)
346 (inferior-prolog-run name))
347 (pop-to-buffer inferior-prolog-buffer))
d8025917 348
23f2d048
SM
349(defun inferior-prolog-self-insert-command ()
350 "Insert the char in the buffer or pass it directly to the process."
351 (interactive)
352 (let* ((proc (get-buffer-process (current-buffer)))
353 (pmark (and proc (marker-position (process-mark proc)))))
354 (if (and (eq inferior-prolog-flavor 'gnu)
355 pmark
356 (null current-prefix-arg)
357 (eobp)
358 (eq (point) pmark)
359 (save-excursion
360 (goto-char (- pmark 3))
361 (looking-at " \\? ")))
362 (comint-send-string proc (string last-command-char))
363 (call-interactively 'self-insert-command))))
364
d8025917 365(defun prolog-consult-region (compile beg end)
573f9b32
RS
366 "Send the region to the Prolog process made by \"M-x run-prolog\".
367If COMPILE (prefix arg) is not nil, use compile mode rather than consult mode."
d8025917 368 (interactive "P\nr")
d364dee6
SM
369 (let ((proc (inferior-prolog-process)))
370 (comint-send-string proc
371 (if compile prolog-compile-string
372 prolog-consult-string))
373 (comint-send-region proc beg end)
374 (comint-send-string proc "\n") ;May be unnecessary
d8025917 375 (if prolog-eof-string
d364dee6
SM
376 (comint-send-string proc prolog-eof-string)
377 (with-current-buffer (process-buffer proc)
378 (comint-send-eof))))) ;Send eof to prolog process.
d8025917 379
380(defun prolog-consult-region-and-go (compile beg end)
381 "Send the region to the inferior Prolog, and switch to *prolog* buffer.
573f9b32 382If COMPILE (prefix arg) is not nil, use compile mode rather than consult mode."
d8025917 383 (interactive "P\nr")
384 (prolog-consult-region compile beg end)
23f2d048 385 (pop-to-buffer inferior-prolog-buffer))
6594deb0 386
d364dee6
SM
387(defun inferior-prolog-load-file ()
388 "Pass the current buffer's file to the inferior prolog process."
389 (interactive)
390 (save-buffer)
391 (let ((file buffer-file-name)
392 (proc (inferior-prolog-process)))
393 (with-current-buffer (process-buffer proc)
394 (comint-send-string proc (concat "['" (file-relative-name file) "'].\n"))
395 (pop-to-buffer (current-buffer)))))
396
896546cd
RS
397(provide 'prolog)
398
d364dee6 399;; arch-tag: f3ec6748-1272-4ab6-8826-c50cb1607636
6594deb0 400;;; prolog.el ends here