aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorStefan Monnier2012-05-11 16:05:19 -0400
committerStefan Monnier2012-05-11 16:05:19 -0400
commit2171cea5fcc5537bf6179284bdce554d80982594 (patch)
tree73f67010ad5e3521586eea03e8301f5542013e06 /lisp
parentaa0382bd67c77578fc2e589ba802f5f1330a4a0a (diff)
downloademacs-2171cea5fcc5537bf6179284bdce554d80982594.tar.gz
emacs-2171cea5fcc5537bf6179284bdce554d80982594.zip
* lisp/progmodes/prolog.el: Use SMIE. Cleanup regexp setup.
(prolog-upper-case-string, prolog-lower-case-string) (prolog-atom-char-regexp, prolog-atom-regexp): Initialize in defconst. (prolog-use-smie, prolog-smie-grammar): New vars. (prolog-smie-forward-token, prolog-smie-backward-token) (prolog-smie-rules): New funs. (prolog-comment-indent): Remove. (prolog-mode-variables): Use default comment indentation instead. Setup SMIE. (prolog-build-case-strings, prolog-set-atom-regexps): Remove. (prolog-mode): Don't call them any more. (prolog-electric-colon, prolog-electric-dash) (prolog-edit-menu-insert-move): Use indent-according-to-mode.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/ChangeLog14
-rw-r--r--lisp/progmodes/prolog.el433
2 files changed, 271 insertions, 176 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 467e7f06457..9fe7106c93c 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,19 @@
12012-05-11 Stefan Monnier <monnier@iro.umontreal.ca> 12012-05-11 Stefan Monnier <monnier@iro.umontreal.ca>
2 2
3 * progmodes/prolog.el: Use SMIE. Cleanup regexp setup.
4 (prolog-upper-case-string, prolog-lower-case-string)
5 (prolog-atom-char-regexp, prolog-atom-regexp): Initialize in defconst.
6 (prolog-use-smie, prolog-smie-grammar): New vars.
7 (prolog-smie-forward-token, prolog-smie-backward-token)
8 (prolog-smie-rules): New funs.
9 (prolog-comment-indent): Remove.
10 (prolog-mode-variables): Use default comment indentation instead.
11 Setup SMIE.
12 (prolog-build-case-strings, prolog-set-atom-regexps): Remove.
13 (prolog-mode): Don't call them any more.
14 (prolog-electric-colon, prolog-electric-dash)
15 (prolog-edit-menu-insert-move): Use indent-according-to-mode.
16
3 * dabbrev.el (dabbrev-expand): Make "no expansion found" a user-error. 17 * dabbrev.el (dabbrev-expand): Make "no expansion found" a user-error.
4 18
5 * minibuffer.el (completion--twq-all): Again, allow case differences. 19 * minibuffer.el (completion--twq-all): Again, allow case differences.
diff --git a/lisp/progmodes/prolog.el b/lisp/progmodes/prolog.el
index 4ef6c31442d..16d85cb2d79 100644
--- a/lisp/progmodes/prolog.el
+++ b/lisp/progmodes/prolog.el
@@ -833,18 +833,116 @@ This is really kludgy, and unneeded (i.e. obsolete) in Emacs>=24."
833 ) 833 )
834 table)) 834 table))
835(defvar prolog-mode-abbrev-table nil) 835(defvar prolog-mode-abbrev-table nil)
836(defvar prolog-upper-case-string "" 836
837 "A string containing all upper case characters. 837(if (eval-when-compile
838Set by prolog-build-case-strings.") 838 (and (string-match "[[:upper:]]" "A")
839(defvar prolog-lower-case-string "" 839 (with-temp-buffer
840 "A string containing all lower case characters. 840 (insert "A") (skip-chars-backward "[:upper:]") (bolp))))
841Set by prolog-build-case-strings.") 841 (progn
842 842 (defconst prolog-upper-case-string "[:upper:]"
843(defvar prolog-atom-char-regexp "" 843 "A string containing a char-range matching all upper case characters.")
844 "Set by prolog-set-atom-regexps.") 844 (defconst prolog-lower-case-string "[:lower:]"
845;; "Regexp specifying characters which constitute atoms without quoting.") 845 "A string containing a char-range matching all lower case characters."))
846(defvar prolog-atom-regexp "" 846
847 "Set by prolog-set-atom-regexps.") 847 ;; GNU Emacs compatibility: GNU Emacs does not differentiate between
848 ;; ints and chars, or at least these two are interchangeable.
849 (defalias 'prolog-int-to-char
850 (if (fboundp 'int-to-char) #'int-to-char #'identity))
851
852 (defalias 'prolog-char-to-int
853 (if (fboundp 'char-to-int) #'char-to-int #'identity))
854
855 (defun prolog-ints-intervals (ints)
856 "Return a list of intervals (from . to) covering INTS."
857 (when ints
858 (setq ints (sort ints '<))
859 (let ((prev (car ints))
860 (interval-start (car ints))
861 intervals)
862 (while ints
863 (let ((next (car ints)))
864 (when (> next (1+ prev)) ; start of new interval
865 (setq intervals (cons (cons interval-start prev) intervals))
866 (setq interval-start next))
867 (setq prev next)
868 (setq ints (cdr ints))))
869 (setq intervals (cons (cons interval-start prev) intervals))
870 (reverse intervals))))
871
872 (defun prolog-dash-letters (string)
873 "Return a condensed regexp covering all letters in STRING."
874 (let ((intervals (prolog-ints-intervals (mapcar #'prolog-char-to-int
875 (string-to-list string))))
876 codes)
877 (while intervals
878 (let* ((i (car intervals))
879 (from (car i))
880 (to (cdr i))
881 (c (cond ((= from to) `(,from))
882 ((= (1+ from) to) `(,from ,to))
883 (t `(,from ?- ,to)))))
884 (setq codes (cons c codes)))
885 (setq intervals (cdr intervals)))
886 (apply 'concat (reverse codes))))
887
888 (let ((up_string "")
889 (low_string ""))
890 ;; Use `map-char-table' if it is defined. Otherwise enumerate all
891 ;; numbers between 0 and 255. `map-char-table' is probably safer.
892 ;;
893 ;; `map-char-table' causes problems under Emacs 23.0.0.1, the
894 ;; while loop seems to do its job well (Ryszard Szopa)
895 ;;
896 ;;(if (and (not (featurep 'xemacs))
897 ;; (fboundp 'map-char-table))
898 ;; (map-char-table
899 ;; (lambda (key value)
900 ;; (cond
901 ;; ((and
902 ;; (eq (prolog-int-to-char key) (downcase key))
903 ;; (eq (prolog-int-to-char key) (upcase key)))
904 ;; ;; Do nothing if upper and lower case are the same
905 ;; )
906 ;; ((eq (prolog-int-to-char key) (downcase key))
907 ;; ;; The char is lower case
908 ;; (setq low_string (format "%s%c" low_string key)))
909 ;; ((eq (prolog-int-to-char key) (upcase key))
910 ;; ;; The char is upper case
911 ;; (setq up_string (format "%s%c" up_string key)))
912 ;; ))
913 ;; (current-case-table))
914 ;; `map-char-table' was undefined.
915 (let ((key 0))
916 (while (< key 256)
917 (cond
918 ((and
919 (eq (prolog-int-to-char key) (downcase key))
920 (eq (prolog-int-to-char key) (upcase key)))
921 ;; Do nothing if upper and lower case are the same
922 )
923 ((eq (prolog-int-to-char key) (downcase key))
924 ;; The char is lower case
925 (setq low_string (format "%s%c" low_string key)))
926 ((eq (prolog-int-to-char key) (upcase key))
927 ;; The char is upper case
928 (setq up_string (format "%s%c" up_string key)))
929 )
930 (setq key (1+ key))))
931 ;; )
932 ;; The strings are single-byte strings.
933 (defconst prolog-upper-case-string (prolog-dash-letters up_string)
934 "A string containing a char-range matching all upper case characters.")
935 (defconst prolog-lower-case-string (prolog-dash-letters low_string)
936 "A string containing a char-range matching all lower case characters.")
937 ))
938
939(defconst prolog-atom-char-regexp
940 (if (string-match "[[:alnum:]]" "0")
941 "[[:alnum:]_$]"
942 (format "[%s%s0-9_$]" prolog-lower-case-string prolog-upper-case-string))
943 "Regexp specifying characters which constitute atoms without quoting.")
944(defconst prolog-atom-regexp
945 (format "[%s$]%s*" prolog-lower-case-string prolog-atom-char-regexp))
848 946
849(defconst prolog-left-paren "[[({]" ;FIXME: Why not \\s(? 947(defconst prolog-left-paren "[[({]" ;FIXME: Why not \\s(?
850 "The characters used as left parentheses for the indentation code.") 948 "The characters used as left parentheses for the indentation code.")
@@ -887,6 +985,96 @@ Set by prolog-build-case-strings.")
887 '(("dcg" . "-->") ("rule" . ":-") ("simplification" . "<=>") 985 '(("dcg" . "-->") ("rule" . ":-") ("simplification" . "<=>")
888 ("propagation" . "==>"))))) 986 ("propagation" . "==>")))))
889 987
988;; SMIE support
989
990(require 'smie)
991
992(defvar prolog-use-smie t)
993
994(defun prolog-smie-forward-token ()
995 ;; FIXME: Add support for 0'<char>, if needed after adding it to
996 ;; syntax-propertize-functions.
997 (forward-comment (point-max))
998 (buffer-substring-no-properties
999 (point)
1000 (progn (cond
1001 ((looking-at "[!;]") (forward-char 1))
1002 ((not (zerop (skip-chars-forward "#&*+-./:<=>?@\\^`~"))))
1003 ((not (zerop (skip-syntax-forward "w_'"))))
1004 ;; In case of non-ASCII punctuation.
1005 ((not (zerop (skip-syntax-forward ".")))))
1006 (point))))
1007
1008(defun prolog-smie-backward-token ()
1009 ;; FIXME: Add support for 0'<char>, if needed after adding it to
1010 ;; syntax-propertize-functions.
1011 (forward-comment (- (point-max)))
1012 (buffer-substring-no-properties
1013 (point)
1014 (progn (cond
1015 ((memq (char-before) '(?! ?\;)) (forward-char -1))
1016 ((not (zerop (skip-chars-backward "#&*+-./:<=>?@\\^`~"))))
1017 ((not (zerop (skip-syntax-backward "w_'"))))
1018 ;; In case of non-ASCII punctuation.
1019 ((not (zerop (skip-syntax-backward ".")))))
1020 (point))))
1021
1022(defconst prolog-smie-grammar
1023 ;; Rather than construct the operator levels table from the BNF,
1024 ;; we directly provide the operator precedences from GNU Prolog's
1025 ;; manual (7.14.10 op/3). The only problem is that GNU Prolog's
1026 ;; manual uses precedence levels in the opposite sense (higher
1027 ;; numbers bind less tightly) than SMIE, so we use negative numbers.
1028 '(("." -10000 -10000)
1029 (":-" -1200 -1200)
1030 ("-->" -1200 -1200)
1031 (";" -1100 -1100)
1032 ("->" -1050 -1050)
1033 ("," -1000 -1000)
1034 ("\\+" -900 -900)
1035 ("=" -700 -700)
1036 ("\\=" -700 -700)
1037 ("=.." -700 -700)
1038 ("==" -700 -700)
1039 ("\\==" -700 -700)
1040 ("@<" -700 -700)
1041 ("@=<" -700 -700)
1042 ("@>" -700 -700)
1043 ("@>=" -700 -700)
1044 ("is" -700 -700)
1045 ("=:=" -700 -700)
1046 ("=\\=" -700 -700)
1047 ("<" -700 -700)
1048 ("=<" -700 -700)
1049 (">" -700 -700)
1050 (">=" -700 -700)
1051 (":" -600 -600)
1052 ("+" -500 -500)
1053 ("-" -500 -500)
1054 ("/\\" -500 -500)
1055 ("\\/" -500 -500)
1056 ("*" -400 -400)
1057 ("/" -400 -400)
1058 ("//" -400 -400)
1059 ("rem" -400 -400)
1060 ("mod" -400 -400)
1061 ("<<" -400 -400)
1062 (">>" -400 -400)
1063 ("**" -200 -200)
1064 ("^" -200 -200)
1065 ;; Prefix
1066 ;; ("+" 200 200)
1067 ;; ("-" 200 200)
1068 ;; ("\\" 200 200)
1069 (:smie-closer-alist (t . "."))
1070 )
1071 "Precedence levels of infix operators.")
1072
1073(defun prolog-smie-rules (kind token)
1074 (pcase (cons kind token)
1075 (`(:elem . basic) prolog-indent-width)
1076 (`(:after . ".") '(column . 0)) ;; To work around smie-closer-alist.
1077 (`(:after . ,(or `":-" `"->" `"-->")) prolog-indent-width)))
890 1078
891 1079
892;;------------------------------------------------------------------- 1080;;-------------------------------------------------------------------
@@ -959,7 +1147,6 @@ VERSION is of the format (Major . Minor)"
959 (set (make-local-variable 'paragraph-separate) paragraph-start) 1147 (set (make-local-variable 'paragraph-separate) paragraph-start)
960 (set (make-local-variable 'paragraph-ignore-fill-prefix) t) 1148 (set (make-local-variable 'paragraph-ignore-fill-prefix) t)
961 (set (make-local-variable 'normal-auto-fill-function) 'prolog-do-auto-fill) 1149 (set (make-local-variable 'normal-auto-fill-function) 'prolog-do-auto-fill)
962 (set (make-local-variable 'indent-line-function) 'prolog-indent-line)
963 (set (make-local-variable 'comment-start) "%") 1150 (set (make-local-variable 'comment-start) "%")
964 (set (make-local-variable 'comment-end) "") 1151 (set (make-local-variable 'comment-end) "")
965 (set (make-local-variable 'comment-add) 1) 1152 (set (make-local-variable 'comment-add) 1)
@@ -968,7 +1155,6 @@ VERSION is of the format (Major . Minor)"
968 ;; inside quoted atoms or strings 1155 ;; inside quoted atoms or strings
969 (format "^\\(\\(%s\\|%s\\|[^\n\'\"%%]\\)*\\)\\(/\\*+ *\\|%%+ *\\)" 1156 (format "^\\(\\(%s\\|%s\\|[^\n\'\"%%]\\)*\\)\\(/\\*+ *\\|%%+ *\\)"
970 prolog-quoted-atom-regexp prolog-string-regexp)) 1157 prolog-quoted-atom-regexp prolog-string-regexp))
971 (set (make-local-variable 'comment-indent-function) 'prolog-comment-indent)
972 (set (make-local-variable 'parens-require-spaces) nil) 1158 (set (make-local-variable 'parens-require-spaces) nil)
973 ;; Initialize Prolog system specific variables 1159 ;; Initialize Prolog system specific variables
974 (dolist (var '(prolog-keywords prolog-types prolog-mode-specificators 1160 (dolist (var '(prolog-keywords prolog-types prolog-mode-specificators
@@ -984,6 +1170,13 @@ VERSION is of the format (Major . Minor)"
984 '(prolog-font-lock-keywords nil nil ((?_ . "w")))) 1170 '(prolog-font-lock-keywords nil nil ((?_ . "w"))))
985 (set (make-local-variable 'syntax-propertize-function) 1171 (set (make-local-variable 'syntax-propertize-function)
986 prolog-syntax-propertize-function) 1172 prolog-syntax-propertize-function)
1173
1174 (if prolog-use-smie
1175 ;; Setup SMIE.
1176 (smie-setup prolog-smie-grammar #'prolog-smie-rules
1177 :forward-token #'prolog-smie-forward-token
1178 :backward-token #'prolog-smie-backward-token)
1179 (set (make-local-variable 'indent-line-function) 'prolog-indent-line))
987 ) 1180 )
988 1181
989(defun prolog-mode-keybindings-common (map) 1182(defun prolog-mode-keybindings-common (map)
@@ -1096,11 +1289,9 @@ if that value is non-nil."
1096 ((eq prolog-system 'gnu) "[GNU]") 1289 ((eq prolog-system 'gnu) "[GNU]")
1097 (t "")))) 1290 (t ""))))
1098 (prolog-mode-variables) 1291 (prolog-mode-variables)
1099 (prolog-build-case-strings)
1100 (prolog-set-atom-regexps)
1101 (dolist (ar prolog-align-rules) (add-to-list 'align-rules-list ar)) 1292 (dolist (ar prolog-align-rules) (add-to-list 'align-rules-list ar))
1102 1293
1103 ;; imenu entry moved to the appropriate hook for consistency 1294 ;; `imenu' entry moved to the appropriate hook for consistency.
1104 1295
1105 ;; Load SICStus debugger if suitable 1296 ;; Load SICStus debugger if suitable
1106 (if (and (eq prolog-system 'sicstus) 1297 (if (and (eq prolog-system 'sicstus)
@@ -1614,7 +1805,8 @@ For use with the `compilation-parse-errors-function' variable."
1614 limit t) 1805 limit t)
1615 (setq filepath (match-string 2))) 1806 (setq filepath (match-string 2)))
1616 1807
1617 ;; ###### Does this work with SICStus under Windows (i.e. backslashes and stuff?) 1808 ;; ###### Does this work with SICStus under Windows
1809 ;; (i.e. backslashes and stuff?)
1618 (if (string-match "\\(.*/\\)\\([^/]*\\)$" filepath) 1810 (if (string-match "\\(.*/\\)\\([^/]*\\)$" filepath)
1619 (progn 1811 (progn
1620 (setq dir (match-string 1 filepath)) 1812 (setq dir (match-string 1 filepath))
@@ -1838,7 +2030,8 @@ Argument BOUND is a buffer position limiting searching."
1838 (defface prolog-builtin-face 2030 (defface prolog-builtin-face
1839 '((((class color) (background light)) (:foreground "Purple")) 2031 '((((class color) (background light)) (:foreground "Purple"))
1840 (((class color) (background dark)) (:foreground "Cyan")) 2032 (((class color) (background dark)) (:foreground "Cyan"))
1841 (((class grayscale) (background light)) (:foreground "LightGray" :bold t)) 2033 (((class grayscale) (background light))
2034 :foreground "LightGray" :bold t)
1842 (((class grayscale) (background dark)) (:foreground "DimGray" :bold t)) 2035 (((class grayscale) (background dark)) (:foreground "DimGray" :bold t))
1843 (t (:bold t))) 2036 (t (:bold t)))
1844 "Face name to use for compiler warnings." 2037 "Face name to use for compiler warnings."
@@ -2093,20 +2286,6 @@ rigidly along with this one (not yet)."
2093 (prolog-insert-spaces-after-paren)) 2286 (prolog-insert-spaces-after-paren))
2094 )) 2287 ))
2095 2288
2096(defun prolog-comment-indent ()
2097 "Compute prolog comment indentation."
2098 ;; FIXME: Only difference with default behavior is that %%% is not
2099 ;; flushed to column 0 but just left where the user put it.
2100 (cond ((looking-at "%%%") (prolog-indentation-level-of-line))
2101 ((looking-at "%%") (prolog-indent-level))
2102 (t
2103 (save-excursion
2104 (skip-chars-backward " \t")
2105 ;; Insert one space at least, except at left margin.
2106 (max (+ (current-column) (if (bolp) 0 1))
2107 comment-column)))
2108 ))
2109
2110(defun prolog-indent-level () 2289(defun prolog-indent-level ()
2111 "Compute prolog indentation level." 2290 "Compute prolog indentation level."
2112 (save-excursion 2291 (save-excursion
@@ -3200,7 +3379,8 @@ When called with prefix argument ARG, disable zipping instead."
3200 (save-excursion 3379 (save-excursion
3201 (let ((state (prolog-clause-info)) 3380 (let ((state (prolog-clause-info))
3202 (object (prolog-in-object))) 3381 (object (prolog-in-object)))
3203 (if (or (equal (nth 0 state) "") (equal (prolog-in-string-or-comment) 'cmt)) 3382 (if (or (equal (nth 0 state) "")
3383 (equal (prolog-in-string-or-comment) 'cmt))
3204 nil 3384 nil
3205 (if (and (eq prolog-system 'sicstus) 3385 (if (and (eq prolog-system 'sicstus)
3206 object) 3386 object)
@@ -3229,6 +3409,7 @@ STRING should be given if the last search was by `string-match' on STRING."
3229 3409
3230(defun prolog-pred-start () 3410(defun prolog-pred-start ()
3231 "Return the starting point of the first clause of the current predicate." 3411 "Return the starting point of the first clause of the current predicate."
3412 ;; FIXME: Use SMIE.
3232 (save-excursion 3413 (save-excursion
3233 (goto-char (prolog-clause-start)) 3414 (goto-char (prolog-clause-start))
3234 ;; Find first clause, unless it was a directive 3415 ;; Find first clause, unless it was a directive
@@ -3261,8 +3442,9 @@ STRING should be given if the last search was by `string-match' on STRING."
3261 3442
3262(defun prolog-pred-end () 3443(defun prolog-pred-end ()
3263 "Return the position at the end of the last clause of the current predicate." 3444 "Return the position at the end of the last clause of the current predicate."
3445 ;; FIXME: Use SMIE.
3264 (save-excursion 3446 (save-excursion
3265 (goto-char (prolog-clause-end)) ; if we are before the first predicate 3447 (goto-char (prolog-clause-end)) ; If we are before the first predicate.
3266 (goto-char (prolog-clause-start)) 3448 (goto-char (prolog-clause-start))
3267 (let* ((pinfo (prolog-clause-info)) 3449 (let* ((pinfo (prolog-clause-info))
3268 (predname (nth 0 pinfo)) 3450 (predname (nth 0 pinfo))
@@ -3517,6 +3699,7 @@ If already at the end of clause, move to next clause."
3517(defun prolog-beginning-of-predicate () 3699(defun prolog-beginning-of-predicate ()
3518 "Go to the nearest beginning of predicate before current point. 3700 "Go to the nearest beginning of predicate before current point.
3519Return the final point or nil if no such a beginning was found." 3701Return the final point or nil if no such a beginning was found."
3702 ;; FIXME: Hook into beginning-of-defun.
3520 (interactive) 3703 (interactive)
3521 (let ((op (point)) 3704 (let ((op (point))
3522 (pos (prolog-pred-start))) 3705 (pos (prolog-pred-start)))
@@ -3536,6 +3719,7 @@ Return the final point or nil if no such a beginning was found."
3536 3719
3537(defun prolog-end-of-predicate () 3720(defun prolog-end-of-predicate ()
3538 "Go to the end of the current predicate." 3721 "Go to the end of the current predicate."
3722 ;; FIXME: Hook into end-of-defun.
3539 (interactive) 3723 (interactive)
3540 (let ((op (point))) 3724 (let ((op (point)))
3541 (goto-char (prolog-pred-end)) 3725 (goto-char (prolog-pred-end))
@@ -3657,7 +3841,7 @@ a new comment is created."
3657 "Delete preceding character or whitespace. 3841 "Delete preceding character or whitespace.
3658If `prolog-hungry-delete-key-flag' is non-nil, then all preceding whitespace is 3842If `prolog-hungry-delete-key-flag' is non-nil, then all preceding whitespace is
3659consumed. If however an ARG is supplied, or `prolog-hungry-delete-key-flag' is 3843consumed. If however an ARG is supplied, or `prolog-hungry-delete-key-flag' is
3660nil, or point is inside a literal then the function in the variable 3844nil, or point is inside a literal then the function
3661`backward-delete-char' is called." 3845`backward-delete-char' is called."
3662 (interactive "P") 3846 (interactive "P")
3663 (if (or (not prolog-hungry-delete-key-flag) 3847 (if (or (not prolog-hungry-delete-key-flag)
@@ -3677,6 +3861,7 @@ nil, or point is inside a literal then the function in the variable
3677(defun prolog-electric-if-then-else (arg) 3861(defun prolog-electric-if-then-else (arg)
3678 "If `prolog-electric-if-then-else-flag' is non-nil, indent if-then-else constructs. 3862 "If `prolog-electric-if-then-else-flag' is non-nil, indent if-then-else constructs.
3679Bound to the >, ; and ( keys." 3863Bound to the >, ; and ( keys."
3864 ;; FIXME: Use post-self-insert-hook or electric-indent-mode.
3680 (interactive "P") 3865 (interactive "P")
3681 (self-insert-command (prefix-numeric-value arg)) 3866 (self-insert-command (prefix-numeric-value arg))
3682 (if prolog-electric-if-then-else-flag (prolog-insert-spaces-after-paren))) 3867 (if prolog-electric-if-then-else-flag (prolog-insert-spaces-after-paren)))
@@ -3686,6 +3871,7 @@ Bound to the >, ; and ( keys."
3686That is, insert space (if appropriate), `:-' and newline if colon is pressed 3871That is, insert space (if appropriate), `:-' and newline if colon is pressed
3687at the end of a line that starts in the first column (i.e., clause 3872at the end of a line that starts in the first column (i.e., clause
3688heads)." 3873heads)."
3874 ;; FIXME: Use post-self-insert-hook.
3689 (interactive "P") 3875 (interactive "P")
3690 (if (and prolog-electric-colon-flag 3876 (if (and prolog-electric-colon-flag
3691 (null arg) 3877 (null arg)
@@ -3696,7 +3882,7 @@ heads)."
3696 (unless (save-excursion (backward-char 1) (looking-at "\\s ")) 3882 (unless (save-excursion (backward-char 1) (looking-at "\\s "))
3697 (insert " ")) 3883 (insert " "))
3698 (insert ":-\n") 3884 (insert ":-\n")
3699 (prolog-indent-line)) 3885 (indent-according-to-mode))
3700 (self-insert-command (prefix-numeric-value arg)))) 3886 (self-insert-command (prefix-numeric-value arg))))
3701 3887
3702(defun prolog-electric-dash (arg) 3888(defun prolog-electric-dash (arg)
@@ -3704,6 +3890,7 @@ heads)."
3704that is, insert space (if appropriate), `-->' and newline if dash is pressed 3890that is, insert space (if appropriate), `-->' and newline if dash is pressed
3705at the end of a line that starts in the first column (i.e., DCG 3891at the end of a line that starts in the first column (i.e., DCG
3706heads)." 3892heads)."
3893 ;; FIXME: Use post-self-insert-hook.
3707 (interactive "P") 3894 (interactive "P")
3708 (if (and prolog-electric-dash-flag 3895 (if (and prolog-electric-dash-flag
3709 (null arg) 3896 (null arg)
@@ -3714,7 +3901,7 @@ heads)."
3714 (unless (save-excursion (backward-char 1) (looking-at "\\s ")) 3901 (unless (save-excursion (backward-char 1) (looking-at "\\s "))
3715 (insert " ")) 3902 (insert " "))
3716 (insert "-->\n") 3903 (insert "-->\n")
3717 (prolog-indent-line)) 3904 (indent-according-to-mode))
3718 (self-insert-command (prefix-numeric-value arg)))) 3905 (self-insert-command (prefix-numeric-value arg))))
3719 3906
3720(defun prolog-electric-dot (arg) 3907(defun prolog-electric-dot (arg)
@@ -3729,6 +3916,7 @@ When invoked at the beginning of line, insert a head of a new clause
3729of the current predicate. 3916of the current predicate.
3730 3917
3731When called with prefix argument ARG, insert just dot." 3918When called with prefix argument ARG, insert just dot."
3919 ;; FIXME: Use post-self-insert-hook.
3732 (interactive "P") 3920 (interactive "P")
3733 ;; Check for situations when the electricity should not be active 3921 ;; Check for situations when the electricity should not be active
3734 (if (or (not prolog-electric-dot-flag) 3922 (if (or (not prolog-electric-dot-flag)
@@ -3788,6 +3976,7 @@ If `prolog-electric-underscore-flag' is non-nil and the point is
3788on a variable then replace the variable with underscore and skip 3976on a variable then replace the variable with underscore and skip
3789the following comma and whitespace, if any. 3977the following comma and whitespace, if any.
3790If the point is not on a variable then insert underscore." 3978If the point is not on a variable then insert underscore."
3979 ;; FIXME: Use post-self-insert-hook.
3791 (interactive) 3980 (interactive)
3792 (if prolog-electric-underscore-flag 3981 (if prolog-electric-underscore-flag
3793 (let (;start 3982 (let (;start
@@ -3862,144 +4051,36 @@ PREFIX is the prefix of the search regexp."
3862 (backward-char))) 4051 (backward-char)))
3863 ))) 4052 )))
3864 4053
4054;;(defun prolog-regexp-dash-continuous-chars (chars)
4055;; (let ((ints (mapcar #'prolog-char-to-int (string-to-list chars)))
4056;; (beg 0)
4057;; (end 0))
4058;; (if (null ints)
4059;; chars
4060;; (while (and (< (+ beg 1) (length chars))
4061;; (not (or (= (+ (nth beg ints) 1) (nth (+ beg 1) ints))
4062;; (= (nth beg ints) (nth (+ beg 1) ints)))))
4063;; (setq beg (+ beg 1)))
4064;; (setq beg (+ beg 1)
4065;; end beg)
4066;; (while (and (< (+ end 1) (length chars))
4067;; (or (= (+ (nth end ints) 1) (nth (+ end 1) ints))
4068;; (= (nth end ints) (nth (+ end 1) ints))))
4069;; (setq end (+ end 1)))
4070;; (if (equal (substring chars end) "")
4071;; (substring chars 0 beg)
4072;; (concat (substring chars 0 beg) "-"
4073;; (prolog-regexp-dash-continuous-chars (substring chars end))))
4074;; )))
4075
4076;;(defun prolog-condense-character-sets (regexp)
4077;; "Condense adjacent characters in character sets of REGEXP."
4078;; (let ((next -1))
4079;; (while (setq next (string-match "\\[\\(.*?\\)\\]" regexp (1+ next)))
4080;; (setq regexp (replace-match (prolog-dash-letters (match-string 1 regexp))
4081;; t t regexp 1))))
4082;; regexp)
3865 4083
3866(defun prolog-set-atom-regexps ()
3867 "Set the `prolog-atom-char-regexp' and `prolog-atom-regexp' variables.
3868Must be called after `prolog-build-case-strings'."
3869 (setq prolog-atom-char-regexp
3870 (format "[%s%s0-9_$]"
3871 ;; FIXME: why not a-zA-Z?
3872 prolog-lower-case-string
3873 prolog-upper-case-string))
3874 (setq prolog-atom-regexp
3875 (format "[%s$]%s*"
3876 prolog-lower-case-string
3877 prolog-atom-char-regexp))
3878 )
3879
3880(defun prolog-build-case-strings ()
3881 "Set `prolog-upper-case-string' and `prolog-lower-case-string'.
3882Uses the current case-table for extracting the relevant information."
3883 (let ((up_string "")
3884 (low_string ""))
3885 ;; Use `map-char-table' if it is defined. Otherwise enumerate all
3886 ;; numbers between 0 and 255. `map-char-table' is probably safer.
3887 ;;
3888 ;; `map-char-table' causes problems under Emacs 23.0.0.1, the
3889 ;; while loop seems to do its job well (Ryszard Szopa)
3890 ;;
3891 ;;(if (and (not (featurep 'xemacs))
3892 ;; (fboundp 'map-char-table))
3893 ;; (map-char-table
3894 ;; (lambda (key value)
3895 ;; (cond
3896 ;; ((and
3897 ;; (eq (prolog-int-to-char key) (downcase key))
3898 ;; (eq (prolog-int-to-char key) (upcase key)))
3899 ;; ;; Do nothing if upper and lower case are the same
3900 ;; )
3901 ;; ((eq (prolog-int-to-char key) (downcase key))
3902 ;; ;; The char is lower case
3903 ;; (setq low_string (format "%s%c" low_string key)))
3904 ;; ((eq (prolog-int-to-char key) (upcase key))
3905 ;; ;; The char is upper case
3906 ;; (setq up_string (format "%s%c" up_string key)))
3907 ;; ))
3908 ;; (current-case-table))
3909 ;; `map-char-table' was undefined.
3910 (let ((key 0))
3911 (while (< key 256)
3912 (cond
3913 ((and
3914 (eq (prolog-int-to-char key) (downcase key))
3915 (eq (prolog-int-to-char key) (upcase key)))
3916 ;; Do nothing if upper and lower case are the same
3917 )
3918 ((eq (prolog-int-to-char key) (downcase key))
3919 ;; The char is lower case
3920 (setq low_string (format "%s%c" low_string key)))
3921 ((eq (prolog-int-to-char key) (upcase key))
3922 ;; The char is upper case
3923 (setq up_string (format "%s%c" up_string key)))
3924 )
3925 (setq key (1+ key))))
3926 ;; )
3927 ;; The strings are single-byte strings
3928 (setq prolog-upper-case-string (prolog-dash-letters up_string))
3929 (setq prolog-lower-case-string (prolog-dash-letters low_string))
3930 ))
3931
3932;(defun prolog-regexp-dash-continuous-chars (chars)
3933; (let ((ints (mapcar #'prolog-char-to-int (string-to-list chars)))
3934; (beg 0)
3935; (end 0))
3936; (if (null ints)
3937; chars
3938; (while (and (< (+ beg 1) (length chars))
3939; (not (or (= (+ (nth beg ints) 1) (nth (+ beg 1) ints))
3940; (= (nth beg ints) (nth (+ beg 1) ints)))))
3941; (setq beg (+ beg 1)))
3942; (setq beg (+ beg 1)
3943; end beg)
3944; (while (and (< (+ end 1) (length chars))
3945; (or (= (+ (nth end ints) 1) (nth (+ end 1) ints))
3946; (= (nth end ints) (nth (+ end 1) ints))))
3947; (setq end (+ end 1)))
3948; (if (equal (substring chars end) "")
3949; (substring chars 0 beg)
3950; (concat (substring chars 0 beg) "-"
3951; (prolog-regexp-dash-continuous-chars (substring chars end))))
3952; )))
3953
3954(defun prolog-ints-intervals (ints)
3955 "Return a list of intervals (from . to) covering INTS."
3956 (when ints
3957 (setq ints (sort ints '<))
3958 (let ((prev (car ints))
3959 (interval-start (car ints))
3960 intervals)
3961 (while ints
3962 (let ((next (car ints)))
3963 (when (> next (1+ prev)) ; start of new interval
3964 (setq intervals (cons (cons interval-start prev) intervals))
3965 (setq interval-start next))
3966 (setq prev next)
3967 (setq ints (cdr ints))))
3968 (setq intervals (cons (cons interval-start prev) intervals))
3969 (reverse intervals))))
3970
3971(defun prolog-dash-letters (string)
3972 "Return a condensed regexp covering all letters in STRING."
3973 (let ((intervals (prolog-ints-intervals (mapcar #'prolog-char-to-int
3974 (string-to-list string))))
3975 codes)
3976 (while intervals
3977 (let* ((i (car intervals))
3978 (from (car i))
3979 (to (cdr i))
3980 (c (cond ((= from to) `(,from))
3981 ((= (1+ from) to) `(,from ,to))
3982 (t `(,from ?- ,to)))))
3983 (setq codes (cons c codes)))
3984 (setq intervals (cdr intervals)))
3985 (apply 'concat (reverse codes))))
3986
3987;(defun prolog-condense-character-sets (regexp)
3988; "Condense adjacent characters in character sets of REGEXP."
3989; (let ((next -1))
3990; (while (setq next (string-match "\\[\\(.*?\\)\\]" regexp (1+ next)))
3991; (setq regexp (replace-match (prolog-dash-letters (match-string 1 regexp))
3992; t t regexp 1))))
3993; regexp)
3994
3995;; GNU Emacs compatibility: GNU Emacs does not differentiate between
3996;; ints and chars, or at least these two are interchangeable.
3997(defalias 'prolog-int-to-char
3998 (if (fboundp 'int-to-char) #'int-to-char #'identity))
3999
4000(defalias 'prolog-char-to-int
4001 (if (fboundp 'char-to-int) #'char-to-int #'identity))
4002
4003;;------------------------------------------------------------------- 4084;;-------------------------------------------------------------------
4004;; Menu stuff (both for the editing buffer and for the inferior 4085;; Menu stuff (both for the editing buffer and for the inferior
4005;; prolog buffer) 4086;; prolog buffer)
@@ -4110,7 +4191,7 @@ Uses the current case-table for extracting the relevant information."
4110 ["Beginning of predicate" prolog-beginning-of-predicate t] 4191 ["Beginning of predicate" prolog-beginning-of-predicate t]
4111 ["End of predicate" prolog-end-of-predicate t] 4192 ["End of predicate" prolog-end-of-predicate t]
4112 "---" 4193 "---"
4113 ["Indent line" prolog-indent-line t] 4194 ["Indent line" indent-according-to-mode t]
4114 ["Indent region" indent-region (region-exists-p)] 4195 ["Indent region" indent-region (region-exists-p)]
4115 ["Indent predicate" prolog-indent-predicate t] 4196 ["Indent predicate" prolog-indent-predicate t]
4116 ["Indent buffer" prolog-indent-buffer t] 4197 ["Indent buffer" prolog-indent-buffer t]