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