prolog.el 9.66 KB
Newer Older
Eric S. Raymond's avatar
Eric S. Raymond committed
1 2
;;; prolog.el --- major mode for editing and running Prolog under Emacs

Nick Roberts's avatar
Nick Roberts committed
3
;; Copyright (C) 1986, 1987, 2001, 2002, 2003, 2004, 2005, 2006
4
;; Free Software Foundation, Inc.
Eric S. Raymond's avatar
Eric S. Raymond committed
5

Richard M. Stallman's avatar
Richard M. Stallman committed
6
;; Author: Masanobu UMEDA <umerin@mse.kyutech.ac.jp>
Eric S. Raymond's avatar
Eric S. Raymond committed
7
;; Keywords: languages
Eric S. Raymond's avatar
Eric S. Raymond committed
8

root's avatar
root committed
9 10 11 12
;; This file is part of GNU Emacs.

;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
Eric S. Raymond's avatar
Eric S. Raymond committed
13
;; the Free Software Foundation; either version 2, or (at your option)
root's avatar
root committed
14 15 16 17 18 19 20 21
;; any later version.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
Erik Naggum's avatar
Erik Naggum committed
22
;; along with GNU Emacs; see the file COPYING.  If not, write to the
Lute Kamstra's avatar
Lute Kamstra committed
23 24
;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
;; Boston, MA 02110-1301, USA.
root's avatar
root committed
25

26 27 28 29
;;; Commentary:

;; This package provides a major mode for editing Prolog.  It knows
;; about Prolog syntax and comments, and can send regions to an inferior
30
;; Prolog interpreter process.  Font locking is tuned towards GNU Prolog.
31

Eric S. Raymond's avatar
Eric S. Raymond committed
32 33
;;; Code:

34 35 36
(defvar comint-prompt-regexp)


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 41
  :group 'languages)

42

43 44 45 46 47 48
(defcustom prolog-program-name
  (let ((names '("prolog" "gprolog")))
    (while (and names
		(not (executable-find (car names))))
      (setq names (cdr names)))
    (or (car names) "prolog"))
49 50 51
  "*Program name for invoking an inferior Prolog with `run-prolog'."
  :type 'string
  :group 'prolog)
root's avatar
root committed
52

53 54 55 56
(defcustom prolog-consult-string "reconsult(user).\n"
  "*(Re)Consult mode (for C-Prolog and Quintus Prolog). "
  :type 'string
  :group 'prolog)
root's avatar
root committed
57

58 59 60 61
(defcustom prolog-compile-string "compile(user).\n"
  "*Compile mode (for Quintus Prolog)."
  :type 'string
  :group 'prolog)
root's avatar
root committed
62

63
(defcustom prolog-eof-string "end_of_file.\n"
64 65
  "*String that represents end of file for Prolog.
When nil, send actual operating system end of file."
66 67
  :type 'string
  :group 'prolog)
root's avatar
root committed
68

69 70 71 72
(defcustom prolog-indent-width 4
  "Level of indentation in Prolog buffers."
  :type 'integer
  :group 'prolog)
root's avatar
root committed
73

74 75 76 77 78 79 80 81 82 83
(defvar prolog-font-lock-keywords
  '(("\\(#[<=]=>\\|:-\\)\\|\\(#=\\)\\|\\(#[#<>\\/][=\\/]*\\|!\\)"
     0 font-lock-keyword-face)
    ("\\<\\(is\\|write\\|nl\\|read_\\sw+\\)\\>"
     1 font-lock-keyword-face)
    ("^\\(\\sw+\\)\\s-*\\((\\(.+\\))\\)*"
     (1 font-lock-function-name-face)
     (3 font-lock-variable-name-face)))
  "Font-lock keywords for Prolog mode.")

84
(defvar prolog-mode-syntax-table
root's avatar
root committed
85 86 87
  (let ((table (make-syntax-table)))
    (modify-syntax-entry ?_ "w" table)
    (modify-syntax-entry ?\\ "\\" table)
88 89
    (modify-syntax-entry ?/ ". 14" table)
    (modify-syntax-entry ?* ". 23" table)
root's avatar
root committed
90 91 92 93
    (modify-syntax-entry ?+ "." table)
    (modify-syntax-entry ?- "." table)
    (modify-syntax-entry ?= "." table)
    (modify-syntax-entry ?% "<" table)
94
    (modify-syntax-entry ?\n ">" table)
root's avatar
root committed
95 96 97
    (modify-syntax-entry ?< "." table)
    (modify-syntax-entry ?> "." table)
    (modify-syntax-entry ?\' "\"" table)
98
    table))
root's avatar
root committed
99

100
(defvar prolog-mode-abbrev-table nil)
root's avatar
root committed
101 102 103 104
(define-abbrev-table 'prolog-mode-abbrev-table ())

(defun prolog-mode-variables ()
  (make-local-variable 'paragraph-separate)
105
  (setq paragraph-separate (concat "%%\\|$\\|" page-delimiter)) ;'%%..'
root's avatar
root committed
106 107
  (make-local-variable 'paragraph-ignore-fill-prefix)
  (setq paragraph-ignore-fill-prefix t)
Karl Heuer's avatar
Karl Heuer committed
108
  (make-local-variable 'imenu-generic-expression)
109
  (setq imenu-generic-expression '((nil "^\\sw+" 0)))
root's avatar
root committed
110 111 112 113 114
  (make-local-variable 'indent-line-function)
  (setq indent-line-function 'prolog-indent-line)
  (make-local-variable 'comment-start)
  (setq comment-start "%")
  (make-local-variable 'comment-start-skip)
115 116 117
  (setq comment-start-skip "\\(?:%+\\|/\\*+\\)[ \t]*")
  (make-local-variable 'comment-end-skip)
  (setq comment-end-skip "[ \t]*\\(\n\\|\\*+/\\)")
root's avatar
root committed
118
  (make-local-variable 'comment-column)
119
  (setq comment-column 48))
root's avatar
root committed
120

121 122 123 124
(defvar prolog-mode-map
  (let ((map (make-sparse-keymap)))
    (define-key map "\e\C-x" 'prolog-consult-region)
    map))
root's avatar
root committed
125

Jim Blandy's avatar
Jim Blandy committed
126
;;;###autoload
root's avatar
root committed
127 128 129 130 131
(defun prolog-mode ()
  "Major mode for editing Prolog code for Prologs.
Blank lines and `%%...' separate paragraphs.  `%'s start comments.
Commands:
\\{prolog-mode-map}
132
Entry to this mode calls the value of `prolog-mode-hook'
root's avatar
root committed
133 134 135 136
if that value is non-nil."
  (interactive)
  (kill-all-local-variables)
  (use-local-map prolog-mode-map)
137
  (set-syntax-table prolog-mode-syntax-table)
root's avatar
root committed
138 139 140
  (setq major-mode 'prolog-mode)
  (setq mode-name "Prolog")
  (prolog-mode-variables)
141 142 143 144
  ;; font lock
  (setq font-lock-defaults '(prolog-font-lock-keywords
                             nil nil nil
                             beginning-of-line))
145
  (run-mode-hooks 'prolog-mode-hook))
root's avatar
root committed
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165

(defun prolog-indent-line (&optional whole-exp)
  "Indent current line as Prolog code.
With argument, indent any additional lines of the same clause
rigidly along with this one (not yet)."
  (interactive "p")
  (let ((indent (prolog-indent-level))
	(pos (- (point-max) (point))) beg)
    (beginning-of-line)
    (setq beg (point))
    (skip-chars-forward " \t")
    (if (zerop (- indent (current-column)))
	nil
      (delete-region beg (point))
      (indent-to indent))
    (if (> (- (point-max) pos) (point))
	(goto-char (- (point-max) pos)))
    ))

(defun prolog-indent-level ()
166
  "Compute Prolog indentation level."
root's avatar
root committed
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
  (save-excursion
    (beginning-of-line)
    (skip-chars-forward " \t")
    (cond
     ((looking-at "%%%") 0)		;Large comment starts
     ((looking-at "%[^%]") comment-column) ;Small comment starts
     ((bobp) 0)				;Beginning of buffer
     (t
      (let ((empty t) ind more less)
	(if (looking-at ")")
	    (setq less t)		;Find close
	  (setq less nil))
	;; See previous indentation
	(while empty
	  (forward-line -1)
	  (beginning-of-line)
 	  (if (bobp)
 	      (setq empty nil)
 	    (skip-chars-forward " \t")
 	    (if (not (or (looking-at "%[^%]") (looking-at "\n")))
 		(setq empty nil))))
 	(if (bobp)
 	    (setq ind 0)		;Beginning of buffer
	  (setq ind (current-column)))	;Beginning of clause
	;; See its beginning
	(if (looking-at "%%[^%]")
	    ind
	  ;; Real prolog code
	  (if (looking-at "(")
	      (setq more t)		;Find open
	    (setq more nil))
	  ;; See its tail
	  (end-of-prolog-clause)
	  (or (bobp) (forward-char -1))
	  (cond ((looking-at "[,(;>]")
		 (if (and more (looking-at "[^,]"))
		     (+ ind prolog-indent-width) ;More indentation
		   (max tab-width ind))) ;Same indentation
		((looking-at "-") tab-width) ;TAB
		((or less (looking-at "[^.]"))
		 (max (- ind prolog-indent-width) 0)) ;Less indentation
		(t 0))			;No indentation
	  )))
     )))

(defun end-of-prolog-clause ()
  "Go to end of clause in this line."
  (beginning-of-line 1)
  (let* ((eolpos (save-excursion (end-of-line) (point))))
    (if (re-search-forward comment-start-skip eolpos 'move)
	(goto-char (match-beginning 0)))
    (skip-chars-backward " \t")))

;;;
;;; Inferior prolog mode
;;;
223 224 225 226 227 228 229 230
(defvar inferior-prolog-mode-map
  (let ((map (make-sparse-keymap)))
    ;; This map will inherit from `comint-mode-map' when entering
    ;; inferior-prolog-mode.
    map))

(defvar inferior-prolog-mode-syntax-table prolog-mode-syntax-table)
(defvar inferior-prolog-mode-abbrev-table prolog-mode-abbrev-table)
root's avatar
root committed
231

232
(define-derived-mode inferior-prolog-mode comint-mode "Inferior Prolog"
root's avatar
root committed
233 234 235 236 237
  "Major mode for interacting with an inferior Prolog process.

The following commands are available:
\\{inferior-prolog-mode-map}

238 239 240
Entry to this mode calls the value of `prolog-mode-hook' with no arguments,
if that value is non-nil.  Likewise with the value of `comint-mode-hook'.
`prolog-mode-hook' is called after `comint-mode-hook'.
root's avatar
root committed
241

242 243
You can send text to the inferior Prolog from other buffers using the commands
`process-send-region', `process-send-string' and \\[prolog-consult-region].
root's avatar
root committed
244 245 246 247

Commands:
Tab indents for Prolog; with argument, shifts rest
 of expression rigidly with the current line.
248 249
Paragraphs are separated only by blank lines and '%%'.
'%'s start comments.
root's avatar
root committed
250 251 252 253 254 255

Return at end of buffer sends line as input.
Return not at end copies rest of line to end and sends it.
\\[comint-kill-input] and \\[backward-kill-word] are kill commands, imitating normal Unix input editing.
\\[comint-interrupt-subjob] interrupts the shell or its current subjob if any.
\\[comint-stop-subjob] stops. \\[comint-quit-subjob] sends quit signal."
256 257
  (setq comint-prompt-regexp "^| [ ?][- ] *")
  (prolog-mode-variables))
root's avatar
root committed
258

Jim Blandy's avatar
Jim Blandy committed
259
;;;###autoload
root's avatar
root committed
260 261 262 263
(defun run-prolog ()
  "Run an inferior Prolog process, input and output via buffer *prolog*."
  (interactive)
  (require 'comint)
264
  (pop-to-buffer (make-comint "prolog" prolog-program-name))
root's avatar
root committed
265 266 267
  (inferior-prolog-mode))

(defun prolog-consult-region (compile beg end)
268 269
  "Send the region to the Prolog process made by \"M-x run-prolog\".
If COMPILE (prefix arg) is not nil, use compile mode rather than consult mode."
root's avatar
root committed
270 271 272
  (interactive "P\nr")
  (save-excursion
    (if compile
273 274 275 276
	(process-send-string "prolog" prolog-compile-string)
      (process-send-string "prolog" prolog-consult-string))
    (process-send-region "prolog" beg end)
    (process-send-string "prolog" "\n")		;May be unnecessary
root's avatar
root committed
277
    (if prolog-eof-string
278
	(process-send-string "prolog" prolog-eof-string)
root's avatar
root committed
279 280 281 282
      (process-send-eof "prolog")))) ;Send eof to prolog process.

(defun prolog-consult-region-and-go (compile beg end)
  "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."
root's avatar
root committed
284 285 286
  (interactive "P\nr")
  (prolog-consult-region compile beg end)
  (switch-to-buffer "*prolog*"))
Eric S. Raymond's avatar
Eric S. Raymond committed
287

Richard M. Stallman's avatar
Richard M. Stallman committed
288 289
(provide 'prolog)

Miles Bader's avatar
Miles Bader committed
290
;;; arch-tag: f3ec6748-1272-4ab6-8826-c50cb1607636
Eric S. Raymond's avatar
Eric S. Raymond committed
291
;;; prolog.el ends here