Merge from trunk.
[bpt/emacs.git] / lisp / progmodes / prolog.el
index bb72984..8971e97 100644 (file)
@@ -1,9 +1,9 @@
-;;; prolog.el --- major mode for editing and running Prolog (and Mercury) code
+;;; prolog.el --- major mode for Prolog (and Mercury) -*- coding: utf-8 -*-
 
-;; Copyright (C) 1986-1987, 1997-1999, 2002-2003, 2011-2012
-;;   Free Software Foundation, Inc.
+;; Copyright (C) 1986-1987, 1997-1999, 2002-2003, 2011-2013 Free
+;; Software Foundation, Inc.
 
-;; Authors: Emil Åström <emil_astrom(at)hotmail(dot)com>
+;; Authors: Emil Åström <emil_astrom(at)hotmail(dot)com>
 ;;          Milan Zamazal <pdm(at)freesoft(dot)cz>
 ;;          Stefan Bruda <stefan(at)bruda(dot)ca>
 ;;          * See below for more details
 ;; Original author: Masanobu UMEDA <umerin(at)mse(dot)kyutech(dot)ac(dot)jp>
 ;; Parts of this file was taken from a modified version of the original
 ;; by Johan Andersson, Peter Olin, Mats Carlsson, Johan Bevemyr, Stefan
-;; Andersson, and Per Danielsson (all SICS people), and Henrik Båkman
+;; Andersson, and Per Danielsson (all SICS people), and Henrik Båkman
 ;; at Uppsala University, Sweden.
 ;;
 ;; Some ideas and also a few lines of code have been borrowed (not stolen ;-)
 ;; from Oz.el, the Emacs major mode for the Oz programming language,
 ;; Copyright (C) 1993 DFKI GmbH, Germany, with permission.
-;; Authors: Ralf Scheidhauer and Michael Mehl ([scheidhr|mehl](at)dfki(dot)uni-sb(dot)de)
+;; Authored by Ralf Scheidhauer and Michael Mehl
+;;   ([scheidhr|mehl](at)dfki(dot)uni-sb(dot)de)
 ;;
 ;; More ideas and code have been taken from the SICStus debugger mode
 ;; (http://www.csd.uu.se/~perm/source_debug/index.shtml -- broken link
@@ -59,9 +60,7 @@
 
 ;;; Installation:
 ;;
-;; Insert the following lines in your init file--typically ~/.emacs
-;; (GNU Emacs and XEmacs <21.4), or ~/.xemacs/init.el (XEmacs
-;; 21.4)--to use this mode when editing Prolog files under Emacs:
+;; Insert the following lines in your init file:
 ;;
 ;; (setq load-path (cons "/usr/lib/xemacs/site-lisp" load-path))
 ;; (autoload 'run-prolog "prolog" "Start a Prolog sub-process." t)
 
 
 (defgroup prolog nil
-  "Major modes for editing and running Prolog and Mercury files."
+  "Editing and running Prolog and Mercury files."
   :group 'languages)
 
 (defgroup prolog-faces nil
@@ -832,18 +831,116 @@ This is really kludgy, and unneeded (i.e. obsolete) in Emacs>=24."
       )
     table))
 (defvar prolog-mode-abbrev-table nil)
-(defvar prolog-upper-case-string ""
-  "A string containing all upper case characters.
-Set by prolog-build-case-strings.")
-(defvar prolog-lower-case-string ""
-  "A string containing all lower case characters.
-Set by prolog-build-case-strings.")
-
-(defvar prolog-atom-char-regexp ""
-  "Set by prolog-set-atom-regexps.")
-;; "Regexp specifying characters which constitute atoms without quoting.")
-(defvar prolog-atom-regexp ""
-  "Set by prolog-set-atom-regexps.")
+
+(if (eval-when-compile
+      (and (string-match "[[:upper:]]" "A")
+           (with-temp-buffer
+             (insert "A") (skip-chars-backward "[:upper:]") (bolp))))
+    (progn
+      (defconst prolog-upper-case-string "[:upper:]"
+        "A string containing a char-range matching all upper case characters.")
+      (defconst prolog-lower-case-string "[:lower:]"
+        "A string containing a char-range matching all lower case characters."))
+
+  ;; GNU Emacs compatibility: GNU Emacs does not differentiate between
+  ;; ints and chars, or at least these two are interchangeable.
+  (defalias 'prolog-int-to-char
+    (if (fboundp 'int-to-char) #'int-to-char #'identity))
+
+  (defalias 'prolog-char-to-int
+    (if (fboundp 'char-to-int) #'char-to-int #'identity))
+
+  (defun prolog-ints-intervals (ints)
+    "Return a list of intervals (from . to) covering INTS."
+    (when ints
+      (setq ints (sort ints '<))
+      (let ((prev (car ints))
+            (interval-start (car ints))
+            intervals)
+        (while ints
+          (let ((next (car ints)))
+            (when (> next (1+ prev))   ; start of new interval
+             (setq intervals (cons (cons interval-start prev) intervals))
+             (setq interval-start next))
+            (setq prev next)
+            (setq ints (cdr ints))))
+        (setq intervals (cons (cons interval-start prev) intervals))
+        (reverse intervals))))
+
+  (defun prolog-dash-letters (string)
+    "Return a condensed regexp covering all letters in STRING."
+    (let ((intervals (prolog-ints-intervals (mapcar #'prolog-char-to-int
+                                                    (string-to-list string))))
+          codes)
+      (while intervals
+        (let* ((i (car intervals))
+               (from (car i))
+               (to (cdr i))
+               (c (cond ((= from to) `(,from))
+                        ((= (1+ from) to) `(,from ,to))
+                        (t `(,from ?- ,to)))))
+          (setq codes (cons c codes)))
+        (setq intervals (cdr intervals)))
+      (apply 'concat (reverse codes))))
+
+  (let ((up_string "")
+        (low_string ""))
+    ;; Use `map-char-table' if it is defined. Otherwise enumerate all
+    ;; numbers between 0 and 255. `map-char-table' is probably safer.
+    ;;
+    ;; `map-char-table' causes problems under Emacs 23.0.0.1, the
+    ;; while loop seems to do its job well (Ryszard Szopa)
+    ;;
+    ;;(if (and (not (featurep 'xemacs))
+    ;;          (fboundp 'map-char-table))
+    ;;    (map-char-table
+    ;;     (lambda (key value)
+    ;;       (cond
+    ;;        ((and
+    ;;          (eq (prolog-int-to-char key) (downcase key))
+    ;;          (eq (prolog-int-to-char key) (upcase key)))
+    ;;         ;; Do nothing if upper and lower case are the same
+    ;;         )
+    ;;        ((eq (prolog-int-to-char key) (downcase key))
+    ;;         ;; The char is lower case
+    ;;         (setq low_string (format "%s%c" low_string key)))
+    ;;        ((eq (prolog-int-to-char key) (upcase key))
+    ;;         ;; The char is upper case
+    ;;         (setq up_string (format "%s%c" up_string key)))
+    ;;        ))
+    ;;     (current-case-table))
+    ;; `map-char-table' was undefined.
+    (let ((key 0))
+      (while (< key 256)
+        (cond
+         ((and
+           (eq (prolog-int-to-char key) (downcase key))
+           (eq (prolog-int-to-char key) (upcase key)))
+          ;; Do nothing if upper and lower case are the same
+          )
+         ((eq (prolog-int-to-char key) (downcase key))
+          ;; The char is lower case
+          (setq low_string (format "%s%c" low_string key)))
+         ((eq (prolog-int-to-char key) (upcase key))
+          ;; The char is upper case
+          (setq up_string (format "%s%c" up_string key)))
+         )
+        (setq key (1+ key))))
+    ;; )
+    ;; The strings are single-byte strings.
+    (defconst prolog-upper-case-string (prolog-dash-letters up_string)
+      "A string containing a char-range matching all upper case characters.")
+    (defconst prolog-lower-case-string (prolog-dash-letters low_string)
+      "A string containing a char-range matching all lower case characters.")
+    ))
+
+(defconst prolog-atom-char-regexp
+  (if (string-match "[[:alnum:]]" "0")
+      "[[:alnum:]_$]"
+    (format "[%s%s0-9_$]" prolog-lower-case-string prolog-upper-case-string))
+  "Regexp specifying characters which constitute atoms without quoting.")
+(defconst prolog-atom-regexp
+  (format "[%s$]%s*" prolog-lower-case-string prolog-atom-char-regexp))
 
 (defconst prolog-left-paren "[[({]"     ;FIXME: Why not \\s(?
   "The characters used as left parentheses for the indentation code.")
@@ -886,6 +983,96 @@ Set by prolog-build-case-strings.")
      '(("dcg" . "-->") ("rule" . ":-") ("simplification" . "<=>")
        ("propagation" . "==>")))))
 
+;; SMIE support
+
+(require 'smie)
+
+(defvar prolog-use-smie t)
+
+(defun prolog-smie-forward-token ()
+  ;; FIXME: Add support for 0'<char>, if needed after adding it to
+  ;; syntax-propertize-functions.
+  (forward-comment (point-max))
+  (buffer-substring-no-properties
+   (point)
+   (progn (cond
+           ((looking-at "[!;]") (forward-char 1))
+           ((not (zerop (skip-chars-forward "#&*+-./:<=>?@\\^`~"))))
+           ((not (zerop (skip-syntax-forward "w_'"))))
+           ;; In case of non-ASCII punctuation.
+           ((not (zerop (skip-syntax-forward ".")))))
+          (point))))
+
+(defun prolog-smie-backward-token ()
+  ;; FIXME: Add support for 0'<char>, if needed after adding it to
+  ;; syntax-propertize-functions.
+  (forward-comment (- (point-max)))
+  (buffer-substring-no-properties
+   (point)
+   (progn (cond
+           ((memq (char-before) '(?! ?\;)) (forward-char -1))
+           ((not (zerop (skip-chars-backward "#&*+-./:<=>?@\\^`~"))))
+           ((not (zerop (skip-syntax-backward "w_'"))))
+           ;; In case of non-ASCII punctuation.
+           ((not (zerop (skip-syntax-backward ".")))))
+          (point))))
+
+(defconst prolog-smie-grammar
+  ;; Rather than construct the operator levels table from the BNF,
+  ;; we directly provide the operator precedences from GNU Prolog's
+  ;; manual (7.14.10 op/3).  The only problem is that GNU Prolog's
+  ;; manual uses precedence levels in the opposite sense (higher
+  ;; numbers bind less tightly) than SMIE, so we use negative numbers.
+  '(("." -10000 -10000)
+    (":-" -1200 -1200)
+    ("-->" -1200 -1200)
+    (";" -1100 -1100)
+    ("->" -1050 -1050)
+    ("," -1000 -1000)
+    ("\\+" -900 -900)
+    ("=" -700 -700)
+    ("\\=" -700 -700)
+    ("=.." -700 -700)
+    ("==" -700 -700)
+    ("\\==" -700 -700)
+    ("@<" -700 -700)
+    ("@=<" -700 -700)
+    ("@>" -700 -700)
+    ("@>=" -700 -700)
+    ("is" -700 -700)
+    ("=:=" -700 -700)
+    ("=\\=" -700 -700)
+    ("<" -700 -700)
+    ("=<" -700 -700)
+    (">" -700 -700)
+    (">=" -700 -700)
+    (":" -600 -600)
+    ("+" -500 -500)
+    ("-" -500 -500)
+    ("/\\" -500 -500)
+    ("\\/" -500 -500)
+    ("*" -400 -400)
+    ("/" -400 -400)
+    ("//" -400 -400)
+    ("rem" -400 -400)
+    ("mod" -400 -400)
+    ("<<" -400 -400)
+    (">>" -400 -400)
+    ("**" -200 -200)
+    ("^" -200 -200)
+    ;; Prefix
+    ;; ("+" 200 200)
+    ;; ("-" 200 200)
+    ;; ("\\" 200 200)
+    (:smie-closer-alist (t . "."))
+    )
+  "Precedence levels of infix operators.")
+
+(defun prolog-smie-rules (kind token)
+  (pcase (cons kind token)
+    (`(:elem . basic) prolog-indent-width)
+    (`(:after . ".") '(column . 0)) ;; To work around smie-closer-alist.
+    (`(:after . ,(or `":-" `"->" `"-->")) prolog-indent-width)))
 
 \f
 ;;-------------------------------------------------------------------
@@ -958,7 +1145,6 @@ VERSION is of the format (Major . Minor)"
   (set (make-local-variable 'paragraph-separate) paragraph-start)
   (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
   (set (make-local-variable 'normal-auto-fill-function) 'prolog-do-auto-fill)
-  (set (make-local-variable 'indent-line-function) 'prolog-indent-line)
   (set (make-local-variable 'comment-start) "%")
   (set (make-local-variable 'comment-end) "")
   (set (make-local-variable 'comment-add) 1)
@@ -967,7 +1153,6 @@ VERSION is of the format (Major . Minor)"
        ;; inside quoted atoms or strings
        (format "^\\(\\(%s\\|%s\\|[^\n\'\"%%]\\)*\\)\\(/\\*+ *\\|%%+ *\\)"
                prolog-quoted-atom-regexp prolog-string-regexp))
-  (set (make-local-variable 'comment-indent-function) 'prolog-comment-indent)
   (set (make-local-variable 'parens-require-spaces) nil)
   ;; Initialize Prolog system specific variables
   (dolist (var '(prolog-keywords prolog-types prolog-mode-specificators
@@ -983,6 +1168,13 @@ VERSION is of the format (Major . Minor)"
        '(prolog-font-lock-keywords nil nil ((?_ . "w"))))
   (set (make-local-variable 'syntax-propertize-function)
       prolog-syntax-propertize-function)
+
+  (if prolog-use-smie
+      ;; Setup SMIE.
+      (smie-setup prolog-smie-grammar #'prolog-smie-rules
+                  :forward-token #'prolog-smie-forward-token
+                  :backward-token #'prolog-smie-backward-token)
+    (set (make-local-variable 'indent-line-function) 'prolog-indent-line))
   )
 
 (defun prolog-mode-keybindings-common (map)
@@ -1095,11 +1287,9 @@ if that value is non-nil."
                            ((eq prolog-system 'gnu) "[GNU]")
                            (t ""))))
   (prolog-mode-variables)
-  (prolog-build-case-strings)
-  (prolog-set-atom-regexps)
   (dolist (ar prolog-align-rules) (add-to-list 'align-rules-list ar))
 
-  ;; imenu entry moved to the appropriate hook for consistency
+  ;; `imenu' entry moved to the appropriate hook for consistency.
 
   ;; Load SICStus debugger if suitable
   (if (and (eq prolog-system 'sicstus)
@@ -1580,7 +1770,8 @@ This function must be called from the source code buffer."
                                              real-file))
     (with-current-buffer buffer
       (goto-char (point-max))
-      (set-process-filter process 'prolog-consult-compile-filter)
+      (add-function :override (process-filter process)
+                    #'prolog-consult-compile-filter)
       (process-send-string "prolog" command-string)
       ;; (prolog-build-prolog-command compilep file real-file first-line))
       (while (and prolog-process-flag
@@ -1591,7 +1782,8 @@ This function must be called from the source code buffer."
       (insert (if compilep
                   "\nCompilation finished.\n"
                 "\nConsulted.\n"))
-      (set-process-filter process old-filter))))
+      (remove-function (process-filter process)
+                       #'prolog-consult-compile-filter))))
 
 (defvar compilation-error-list)
 
@@ -1613,7 +1805,8 @@ For use with the `compilation-parse-errors-function' variable."
          limit t)
         (setq filepath (match-string 2)))
 
-      ;; ###### Does this work with SICStus under Windows (i.e. backslashes and stuff?)
+      ;; ###### Does this work with SICStus under Windows
+      ;; (i.e. backslashes and stuff?)
       (if (string-match "\\(.*/\\)\\([^/]*\\)$" filepath)
           (progn
             (setq dir (match-string 1 filepath))
@@ -1837,7 +2030,8 @@ Argument BOUND is a buffer position limiting searching."
     (defface prolog-builtin-face
       '((((class color) (background light)) (:foreground "Purple"))
         (((class color) (background dark)) (:foreground "Cyan"))
-        (((class grayscale) (background light)) (:foreground "LightGray" :bold t))
+        (((class grayscale) (background light))
+         :foreground "LightGray" :bold t)
         (((class grayscale) (background dark)) (:foreground "DimGray" :bold t))
         (t (:bold t)))
       "Face name to use for compiler warnings."
@@ -1918,7 +2112,7 @@ Argument BOUND is a buffer position limiting searching."
            (if (eq prolog-system 'mercury)
                (list
                 (prolog-make-keywords-regexp prolog-mode-specificators-i t)
-                0 'font-lock-reference-face)))
+                0 'font-lock-constant-face)))
           (directives
            (if (eq prolog-system 'mercury)
                (list
@@ -2092,20 +2286,6 @@ rigidly along with this one (not yet)."
         (prolog-insert-spaces-after-paren))
     ))
 
-(defun prolog-comment-indent ()
-  "Compute prolog comment indentation."
-  ;; FIXME: Only difference with default behavior is that %%% is not
-  ;; flushed to column 0 but just left where the user put it.
-  (cond ((looking-at "%%%") (prolog-indentation-level-of-line))
-        ((looking-at "%%") (prolog-indent-level))
-        (t
-         (save-excursion
-           (skip-chars-backward " \t")
-           ;; Insert one space at least, except at left margin.
-           (max (+ (current-column) (if (bolp) 0 1))
-                comment-column)))
-        ))
-
 (defun prolog-indent-level ()
   "Compute prolog indentation level."
   (save-excursion
@@ -3199,7 +3379,8 @@ When called with prefix argument ARG, disable zipping instead."
   (save-excursion
     (let ((state (prolog-clause-info))
           (object (prolog-in-object)))
-      (if (or (equal (nth 0 state) "") (equal (prolog-in-string-or-comment) 'cmt))
+      (if (or (equal (nth 0 state) "")
+              (equal (prolog-in-string-or-comment) 'cmt))
           nil
         (if (and (eq prolog-system 'sicstus)
                  object)
@@ -3228,6 +3409,7 @@ STRING should be given if the last search was by `string-match' on STRING."
 
 (defun prolog-pred-start ()
   "Return the starting point of the first clause of the current predicate."
+  ;; FIXME: Use SMIE.
   (save-excursion
     (goto-char (prolog-clause-start))
     ;; Find first clause, unless it was a directive
@@ -3260,8 +3442,9 @@ STRING should be given if the last search was by `string-match' on STRING."
 
 (defun prolog-pred-end ()
   "Return the position at the end of the last clause of the current predicate."
+  ;; FIXME: Use SMIE.
   (save-excursion
-    (goto-char (prolog-clause-end))        ; if we are before the first predicate
+    (goto-char (prolog-clause-end))     ; If we are before the first predicate.
     (goto-char (prolog-clause-start))
     (let* ((pinfo (prolog-clause-info))
           (predname (nth 0 pinfo))
@@ -3516,6 +3699,7 @@ If already at the end of clause, move to next clause."
 (defun prolog-beginning-of-predicate ()
   "Go to the nearest beginning of predicate before current point.
 Return the final point or nil if no such a beginning was found."
+  ;; FIXME: Hook into beginning-of-defun.
   (interactive)
   (let ((op (point))
         (pos (prolog-pred-start)))
@@ -3535,6 +3719,7 @@ Return the final point or nil if no such a beginning was found."
 
 (defun prolog-end-of-predicate ()
   "Go to the end of the current predicate."
+  ;; FIXME: Hook into end-of-defun.
   (interactive)
   (let ((op (point)))
     (goto-char (prolog-pred-end))
@@ -3620,12 +3805,12 @@ a new comment is created."
       (indent-for-comment)))
 
 (defun prolog-indent-predicate ()
-  "*Indent the current predicate."
+  "Indent the current predicate."
   (interactive)
   (indent-region (prolog-pred-start) (prolog-pred-end) nil))
 
 (defun prolog-indent-buffer ()
-  "*Indent the entire buffer."
+  "Indent the entire buffer."
   (interactive)
   (indent-region (point-min) (point-max) nil))
 
@@ -3656,7 +3841,7 @@ a new comment is created."
   "Delete preceding character or whitespace.
 If `prolog-hungry-delete-key-flag' is non-nil, then all preceding whitespace is
 consumed.  If however an ARG is supplied, or `prolog-hungry-delete-key-flag' is
-nil, or point is inside a literal then the function in the variable
+nil, or point is inside a literal then the function
 `backward-delete-char' is called."
   (interactive "P")
   (if (or (not prolog-hungry-delete-key-flag)
@@ -3676,6 +3861,7 @@ nil, or point is inside a literal then the function in the variable
 (defun prolog-electric-if-then-else (arg)
   "If `prolog-electric-if-then-else-flag' is non-nil, indent if-then-else constructs.
 Bound to the >, ; and ( keys."
+  ;; FIXME: Use post-self-insert-hook or electric-indent-mode.
   (interactive "P")
   (self-insert-command (prefix-numeric-value arg))
   (if prolog-electric-if-then-else-flag (prolog-insert-spaces-after-paren)))
@@ -3685,6 +3871,7 @@ Bound to the >, ; and ( keys."
 That is, insert space (if appropriate), `:-' and newline if colon is pressed
 at the end of a line that starts in the first column (i.e., clause
 heads)."
+  ;; FIXME: Use post-self-insert-hook.
   (interactive "P")
   (if (and prolog-electric-colon-flag
           (null arg)
@@ -3695,7 +3882,7 @@ heads)."
         (unless (save-excursion (backward-char 1) (looking-at "\\s "))
           (insert " "))
        (insert ":-\n")
-       (prolog-indent-line))
+        (indent-according-to-mode))
     (self-insert-command (prefix-numeric-value arg))))
 
 (defun prolog-electric-dash (arg)
@@ -3703,6 +3890,7 @@ heads)."
 that is, insert space (if appropriate), `-->' and newline if dash is pressed
 at the end of a line that starts in the first column (i.e., DCG
 heads)."
+  ;; FIXME: Use post-self-insert-hook.
   (interactive "P")
   (if (and prolog-electric-dash-flag
           (null arg)
@@ -3713,7 +3901,7 @@ heads)."
         (unless (save-excursion (backward-char 1) (looking-at "\\s "))
           (insert " "))
        (insert "-->\n")
-       (prolog-indent-line))
+       (indent-according-to-mode))
     (self-insert-command (prefix-numeric-value arg))))
 
 (defun prolog-electric-dot (arg)
@@ -3728,6 +3916,7 @@ When invoked at the beginning of line, insert a head of a new clause
 of the current predicate.
 
 When called with prefix argument ARG, insert just dot."
+  ;; FIXME: Use post-self-insert-hook.
   (interactive "P")
   ;; Check for situations when the electricity should not be active
   (if (or (not prolog-electric-dot-flag)
@@ -3787,6 +3976,7 @@ If `prolog-electric-underscore-flag' is non-nil and the point is
 on a variable then replace the variable with underscore and skip
 the following comma and whitespace, if any.
 If the point is not on a variable then insert underscore."
+  ;; FIXME: Use post-self-insert-hook.
   (interactive)
   (if prolog-electric-underscore-flag
       (let (;start
@@ -3861,144 +4051,36 @@ PREFIX is the prefix of the search regexp."
           (backward-char)))
       )))
 
+;;(defun prolog-regexp-dash-continuous-chars (chars)
+;;  (let ((ints (mapcar #'prolog-char-to-int (string-to-list chars)))
+;;        (beg 0)
+;;        (end 0))
+;;    (if (null ints)
+;;        chars
+;;      (while (and (< (+ beg 1) (length chars))
+;;                  (not (or (= (+ (nth beg ints) 1) (nth (+ beg 1) ints))
+;;                           (= (nth beg ints) (nth (+ beg 1) ints)))))
+;;        (setq beg (+ beg 1)))
+;;      (setq beg (+ beg 1)
+;;            end beg)
+;;      (while (and (< (+ end 1) (length chars))
+;;                  (or (= (+ (nth end ints) 1) (nth (+ end 1) ints))
+;;                      (= (nth end ints) (nth (+ end 1) ints))))
+;;        (setq end (+ end 1)))
+;;      (if (equal (substring chars end) "")
+;;          (substring chars 0 beg)
+;;        (concat (substring chars 0 beg) "-"
+;;                (prolog-regexp-dash-continuous-chars (substring chars end))))
+;;    )))
+
+;;(defun prolog-condense-character-sets (regexp)
+;;  "Condense adjacent characters in character sets of REGEXP."
+;;  (let ((next -1))
+;;    (while (setq next (string-match "\\[\\(.*?\\)\\]" regexp (1+ next)))
+;;      (setq regexp (replace-match (prolog-dash-letters (match-string 1 regexp))
+;;                               t t regexp 1))))
+;;  regexp)
 
-(defun prolog-set-atom-regexps ()
-  "Set the `prolog-atom-char-regexp' and `prolog-atom-regexp' variables.
-Must be called after `prolog-build-case-strings'."
-  (setq prolog-atom-char-regexp
-        (format "[%s%s0-9_$]"
-                ;; FIXME: why not a-zA-Z?
-                prolog-lower-case-string
-                prolog-upper-case-string))
-  (setq prolog-atom-regexp
-        (format "[%s$]%s*"
-                prolog-lower-case-string
-                prolog-atom-char-regexp))
-  )
-
-(defun prolog-build-case-strings ()
-  "Set `prolog-upper-case-string' and `prolog-lower-case-string'.
-Uses the current case-table for extracting the relevant information."
-  (let ((up_string "")
-        (low_string ""))
-    ;; Use `map-char-table' if it is defined. Otherwise enumerate all
-    ;; numbers between 0 and 255. `map-char-table' is probably safer.
-    ;;
-    ;; `map-char-table' causes problems under Emacs 23.0.0.1, the
-    ;; while loop seems to do its job well (Ryszard Szopa)
-    ;;
-    ;;(if (and (not (featurep 'xemacs))
-    ;;          (fboundp 'map-char-table))
-    ;;    (map-char-table
-    ;;     (lambda (key value)
-    ;;       (cond
-    ;;        ((and
-    ;;          (eq (prolog-int-to-char key) (downcase key))
-    ;;          (eq (prolog-int-to-char key) (upcase key)))
-    ;;         ;; Do nothing if upper and lower case are the same
-    ;;         )
-    ;;        ((eq (prolog-int-to-char key) (downcase key))
-    ;;         ;; The char is lower case
-    ;;         (setq low_string (format "%s%c" low_string key)))
-    ;;        ((eq (prolog-int-to-char key) (upcase key))
-    ;;         ;; The char is upper case
-    ;;         (setq up_string (format "%s%c" up_string key)))
-    ;;        ))
-    ;;     (current-case-table))
-      ;; `map-char-table' was undefined.
-      (let ((key 0))
-        (while (< key 256)
-          (cond
-           ((and
-             (eq (prolog-int-to-char key) (downcase key))
-             (eq (prolog-int-to-char key) (upcase key)))
-            ;; Do nothing if upper and lower case are the same
-            )
-           ((eq (prolog-int-to-char key) (downcase key))
-            ;; The char is lower case
-            (setq low_string (format "%s%c" low_string key)))
-           ((eq (prolog-int-to-char key) (upcase key))
-            ;; The char is upper case
-            (setq up_string (format "%s%c" up_string key)))
-           )
-          (setq key (1+ key))))
-      ;; )
-      ;; The strings are single-byte strings
-      (setq prolog-upper-case-string (prolog-dash-letters up_string))
-      (setq prolog-lower-case-string (prolog-dash-letters low_string))
-      ))
-
-;(defun prolog-regexp-dash-continuous-chars (chars)
-;  (let ((ints (mapcar #'prolog-char-to-int (string-to-list chars)))
-;        (beg 0)
-;        (end 0))
-;    (if (null ints)
-;        chars
-;      (while (and (< (+ beg 1) (length chars))
-;                  (not (or (= (+ (nth beg ints) 1) (nth (+ beg 1) ints))
-;                           (= (nth beg ints) (nth (+ beg 1) ints)))))
-;        (setq beg (+ beg 1)))
-;      (setq beg (+ beg 1)
-;            end beg)
-;      (while (and (< (+ end 1) (length chars))
-;                  (or (= (+ (nth end ints) 1) (nth (+ end 1) ints))
-;                      (= (nth end ints) (nth (+ end 1) ints))))
-;        (setq end (+ end 1)))
-;      (if (equal (substring chars end) "")
-;          (substring chars 0 beg)
-;        (concat (substring chars 0 beg) "-"
-;                (prolog-regexp-dash-continuous-chars (substring chars end))))
-;    )))
-
-(defun prolog-ints-intervals (ints)
-  "Return a list of intervals (from . to) covering INTS."
-  (when ints
-    (setq ints (sort ints '<))
-    (let ((prev (car ints))
-         (interval-start (car ints))
-         intervals)
-      (while ints
-       (let ((next (car ints)))
-         (when (> next (1+ prev))      ; start of new interval
-             (setq intervals (cons (cons interval-start prev) intervals))
-             (setq interval-start next))
-         (setq prev next)
-         (setq ints (cdr ints))))
-      (setq intervals (cons (cons interval-start prev) intervals))
-      (reverse intervals))))
-
-(defun prolog-dash-letters (string)
-  "Return a condensed regexp covering all letters in STRING."
-  (let ((intervals (prolog-ints-intervals (mapcar #'prolog-char-to-int
-                                                (string-to-list string))))
-       codes)
-    (while intervals
-      (let* ((i (car intervals))
-            (from (car i))
-            (to (cdr i))
-            (c (cond ((= from to) `(,from))
-                     ((= (1+ from) to) `(,from ,to))
-                     (t `(,from ?- ,to)))))
-       (setq codes (cons c codes)))
-      (setq intervals (cdr intervals)))
-    (apply 'concat (reverse codes))))
-
-;(defun prolog-condense-character-sets (regexp)
-;  "Condense adjacent characters in character sets of REGEXP."
-;  (let ((next -1))
-;    (while (setq next (string-match "\\[\\(.*?\\)\\]" regexp (1+ next)))
-;      (setq regexp (replace-match (prolog-dash-letters (match-string 1 regexp))
-;                                t t regexp 1))))
-;  regexp)
-
-;; GNU Emacs compatibility: GNU Emacs does not differentiate between
-;; ints and chars, or at least these two are interchangeable.
-(defalias 'prolog-int-to-char
-  (if (fboundp 'int-to-char) #'int-to-char #'identity))
-
-(defalias 'prolog-char-to-int
-  (if (fboundp 'char-to-int) #'char-to-int #'identity))
-\f
 ;;-------------------------------------------------------------------
 ;; Menu stuff (both for the editing buffer and for the inferior
 ;; prolog buffer)
@@ -4109,7 +4191,7 @@ Uses the current case-table for extracting the relevant information."
     ["Beginning of predicate" prolog-beginning-of-predicate t]
     ["End of predicate" prolog-end-of-predicate t]
     "---"
-    ["Indent line" prolog-indent-line t]
+    ["Indent line" indent-according-to-mode t]
     ["Indent region" indent-region (region-exists-p)]
     ["Indent predicate" prolog-indent-predicate t]
     ["Indent buffer" prolog-indent-buffer t]