1 ;;; prolog.el --- major mode for Prolog (and Mercury) -*- lexical-binding:t -*-
3 ;; Copyright (C) 1986-1987, 1997-1999, 2002-2003, 2011-2015 Free
4 ;; Software Foundation, Inc.
6 ;; Authors: Emil Åström <emil_astrom(at)hotmail(dot)com>
7 ;; Milan Zamazal <pdm(at)freesoft(dot)cz>
8 ;; Stefan Bruda <stefan(at)bruda(dot)ca>
9 ;; * See below for more details
10 ;; Maintainer: Stefan Bruda <stefan(at)bruda(dot)ca>
11 ;; Keywords: prolog major mode sicstus swi mercury
13 (defvar prolog-mode-version
"1.22"
14 "Prolog mode version number.")
16 ;; This file is part of GNU Emacs.
18 ;; GNU Emacs is free software: you can redistribute it and/or modify
19 ;; it under the terms of the GNU General Public License as published by
20 ;; the Free Software Foundation, either version 3 of the License, or
21 ;; (at your option) any later version.
23 ;; GNU Emacs is distributed in the hope that it will be useful,
24 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
25 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 ;; GNU General Public License for more details.
28 ;; You should have received a copy of the GNU General Public License
29 ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
31 ;; Original author: Masanobu UMEDA <umerin(at)mse(dot)kyutech(dot)ac(dot)jp>
32 ;; Parts of this file was taken from a modified version of the original
33 ;; by Johan Andersson, Peter Olin, Mats Carlsson, Johan Bevemyr, Stefan
34 ;; Andersson, and Per Danielsson (all SICS people), and Henrik Båkman
35 ;; at Uppsala University, Sweden.
37 ;; Some ideas and also a few lines of code have been borrowed (not stolen ;-)
38 ;; from Oz.el, the Emacs major mode for the Oz programming language,
39 ;; Copyright (C) 1993 DFKI GmbH, Germany, with permission.
40 ;; Authored by Ralf Scheidhauer and Michael Mehl
41 ;; ([scheidhr|mehl](at)dfki(dot)uni-sb(dot)de)
43 ;; More ideas and code have been taken from the SICStus debugger mode
44 ;; (http://www.csd.uu.se/~perm/source_debug/index.shtml -- broken link
45 ;; as of Mon May 5 08:23:48 EDT 2003) by Per Mildner.
47 ;; Additions for ECLiPSe and other helpful suggestions: Stephan Heuel
48 ;; <heuel(at)ipb(dot)uni-bonn(dot)de>
52 ;; This package provides a major mode for editing Prolog code, with
53 ;; all the bells and whistles one would expect, including syntax
54 ;; highlighting and auto indentation. It can also send regions to an
55 ;; inferior Prolog process.
57 ;; The code requires the comint, easymenu, info, imenu, and font-lock
58 ;; libraries. These are normally distributed with GNU Emacs and
63 ;; Insert the following lines in your init file:
65 ;; (setq load-path (cons "/usr/lib/xemacs/site-lisp" load-path))
66 ;; (autoload 'run-prolog "prolog" "Start a Prolog sub-process." t)
67 ;; (autoload 'prolog-mode "prolog" "Major mode for editing Prolog programs." t)
68 ;; (autoload 'mercury-mode "prolog" "Major mode for editing Mercury programs." t)
69 ;; (setq prolog-system 'swi) ; optional, the system you are using;
70 ;; ; see `prolog-system' below for possible values
71 ;; (setq auto-mode-alist (append '(("\\.pl$" . prolog-mode)
72 ;; ("\\.m$" . mercury-mode))
75 ;; where the path in the first line is the file system path to this file.
76 ;; MSDOS paths can be written like "d:/programs/emacs-19.34/site-lisp".
77 ;; Note: In XEmacs, either `/usr/lib/xemacs/site-lisp' (RPM default in
78 ;; Red Hat-based distributions) or `/usr/local/lib/xemacs/site-lisp'
79 ;; (default when compiling from sources) are automatically added to
80 ;; `load-path', so the first line is not necessary provided that you
81 ;; put this file in the appropriate place.
83 ;; The last s-expression above makes sure that files ending with .pl
84 ;; are assumed to be Prolog files and not Perl, which is the default
85 ;; Emacs setting. If this is not wanted, remove this line. It is then
86 ;; necessary to either
88 ;; o insert in your Prolog files the following comment as the first line:
90 ;; % -*- Mode: Prolog -*-
92 ;; and then the file will be open in Prolog mode no matter its
95 ;; o manually switch to prolog mode after opening a Prolog file, by typing
98 ;; If the command to start the prolog process ('sicstus', 'pl' or
99 ;; 'swipl' for SWI prolog, etc.) is not available in the default path,
100 ;; then it is necessary to set the value of the environment variable
101 ;; EPROLOG to a shell command to invoke the prolog process. In XEmacs
102 ;; and Emacs 20+ you can also customize the variable
103 ;; `prolog-program-name' (in the group `prolog-inferior') and provide
104 ;; a full path for your Prolog system (swi, scitus, etc.).
106 ;; Note: I (Stefan, the current maintainer) work under XEmacs. Future
107 ;; developments will thus be biased towards XEmacs (OK, I admit it,
108 ;; I am biased towards XEmacs in general), though I will do my best
109 ;; to keep the GNU Emacs compatibility. So if you work under Emacs
110 ;; and see something that does not work do drop me a line, as I have
111 ;; a smaller chance to notice this kind of bugs otherwise.
116 ;; o Allowed both 'swipl' and 'pl' as names for the SWI Prolog
118 ;; o Atoms that start a line are not blindly colored as
119 ;; predicates. Instead we check that they are followed by ( or
120 ;; :- first. Patch suggested by Guy Wiener.
122 ;; o Cleaned up the code that defines faces. The missing face
123 ;; warnings on some Emacsen should disappear.
125 ;; o Improved the handling of clause start detection and multi-line
126 ;; comments: `prolog-clause-start' no longer finds non-predicate
127 ;; (e.g., capitalized strings) beginning of clauses.
128 ;; `prolog-tokenize' recognizes when the end point is within a
129 ;; multi-line comment.
131 ;; o Minimal changes for Aquamacs inclusion and in general for
132 ;; better coping with finding the Prolog executable. Patch
133 ;; provided by David Reitter
135 ;; o Fixed syntax highlighting for clause heads that do not begin at
136 ;; the beginning of the line.
137 ;; o Fixed compilation warnings under Emacs.
138 ;; o Updated the email address of the current maintainer.
140 ;; o Minor indentation fix (patch by Markus Triska)
141 ;; o `prolog-underscore-wordchar-flag' defaults now to nil (more
142 ;; consistent to other Emacs modes)
144 ;; o Eliminated a possible compilation warning.
146 ;; o Introduced three new customizable variables: electric colon
147 ;; (`prolog-electric-colon-flag', default nil), electric dash
148 ;; (`prolog-electric-dash-flag', default nil), and a possibility
149 ;; to prevent the predicate template insertion from adding commas
150 ;; (`prolog-electric-dot-full-predicate-template', defaults to t
151 ;; since it seems quicker to me to just type those commas). A
152 ;; trivial adaptation of a patch by Markus Triska.
153 ;; o Improved the behavior of electric if-then-else to only skip
154 ;; forward if the parenthesis/semicolon is preceded by
155 ;; whitespace. Once more a trivial adaptation of a patch by
158 ;; o Cleaned up align code. `prolog-align-flag' is eliminated (since
159 ;; on a second thought it does not do anything useful). Added key
160 ;; binding (C-c C-a) and menu entry for alignment.
161 ;; o Condensed regular expressions for lower and upper case
162 ;; characters (GNU Emacs seems to go over the regexp length limit
163 ;; with the original form). My code on the matter was improved
164 ;; considerably by Markus Triska.
165 ;; o Fixed `prolog-insert-spaces-after-paren' (which used an
166 ;; uninitialized variable).
167 ;; o Minor changes to clean up the code and avoid some implicit
168 ;; package requirements.
170 ;; o Removed the use of `map-char-table' in `prolog-build-case-strings'
171 ;; which appears to cause problems in (at least) Emacs 23.0.0.1.
172 ;; o Added if-then-else indentation + corresponding electric
173 ;; characters. New customization: `prolog-electric-if-then-else-flag'
174 ;; o Align support (requires `align'). New customization:
175 ;; `prolog-align-flag'.
176 ;; o Temporary consult files have now the same name throughout the
177 ;; session. This prevents issues with reconsulting a buffer
178 ;; (this event is no longer passed to Prolog as a request to
179 ;; consult a new file).
180 ;; o Adaptive fill mode is now turned on. Comment indentation is
181 ;; still worse than it could be though, I am working on it.
182 ;; o Improved filling and auto-filling capabilities. Now block
183 ;; comments should be [auto-]filled correctly most of the time;
184 ;; the following pattern in particular is worth noting as being
186 ;; <some code here> % some comment here that goes beyond the
187 ;; % rightmost column, possibly combined with
188 ;; % subsequent comment lines
189 ;; o `prolog-char-quote-workaround' now defaults to nil.
190 ;; o Note: Many of the above improvements have been suggested by
191 ;; Markus Triska, who also provided useful patches on the matter
192 ;; when he realized that I was slow in responding. Many thanks.
193 ;; Version 1.11 / 1.12
194 ;; o GNU Emacs compatibility fix for paragraph filling (fixed
195 ;; incorrectly in 1.11, fix fixed in 1.12).
197 ;; o Added paragraph filling in comment blocks and also correct auto
198 ;; filling for comments.
199 ;; o Fixed the possible "Regular expression too big" error in
200 ;; `prolog-electric-dot'.
202 ;; o Parenthesis expressions are now indented by default so that
203 ;; components go one underneath the other, just as for compound
204 ;; terms. You can use the old style (the second and subsequent
205 ;; lines being indented to the right in a parenthesis expression)
206 ;; by setting the customizable variable `prolog-paren-indent-p'
207 ;; (group "Prolog Indentation") to t.
208 ;; o (Somehow awkward) handling of the 0' character escape
209 ;; sequence. I am looking into a better way of doing it but
210 ;; prospects look bleak. If this breaks things for you please let
211 ;; me know and also set the `prolog-char-quote-workaround' (group
212 ;; "Prolog Other") to nil.
214 ;; o Key binding fix.
216 ;; o Fixed a number of issues with the syntax of single quotes,
217 ;; including Debian bug #324520.
219 ;; o Fixed mercury mode menu initialization (Debian bug #226121).
220 ;; o Fixed (i.e., eliminated) Delete remapping (Debian bug #229636).
221 ;; o Corrected indentation for clauses defining quoted atoms.
223 ;; o Keywords fontifying should work in console mode so this is
224 ;; enabled everywhere.
226 ;; o Now supports GNU Prolog--minor adaptation of a patch by Stefan
229 ;; o Info-follow-nearest-node now called correctly under Emacs too
230 ;; (thanks to Nicolas Pelletier). Should be implemented more
231 ;; elegantly (i.e., without compilation warnings) in the future.
233 ;; o Another prompt fix, still in SWI mode (people seem to have
234 ;; changed the prompt of SWI Prolog).
236 ;; o Fixed dots in the end of line comments causing indentation
237 ;; problems. The following code is now correctly indented (note
238 ;; the dot terminating the comment):
240 ;; c(X). % comment here.
242 ;; and so is this (and variants):
244 ;; c(X). /* comment here. */
247 ;; o Revamped the menu system.
248 ;; o Yet another prompt recognition fix (SWI mode).
249 ;; o This is more of a renumbering than a new edition. I promoted
250 ;; the mode to version 1.0 to emphasize the fact that it is now
251 ;; mature and stable enough to be considered production (in my
254 ;; o GNU Emacs compatibility fixes.
256 ;; o prolog-get-predspec is now suitable to be called as
257 ;; imenu-extract-index-name-function. The predicate index works.
258 ;; o Since imenu works now as advertised, prolog-imenu-flag is t
260 ;; o Eliminated prolog-create-predicate-index since the imenu
261 ;; utilities now work well. Actually, this function is also
262 ;; buggy, and I see no reason to fix it since we do not need it
264 ;; o Fixed prolog-pred-start, prolog-clause-start, prolog-clause-info.
265 ;; o Fix for prolog-build-case-strings; now prolog-upper-case-string
266 ;; and prolog-lower-case-string are correctly initialized,
267 ;; o Various font-lock changes; most importantly, block comments (/*
268 ;; ... */) are now correctly fontified in XEmacs even when they
269 ;; extend on multiple lines.
271 ;; o The debug prompt of SWI Prolog is now correctly recognized.
273 ;; o Minor font-lock bug fixes.
277 ;; Replace ":type 'sexp" with more precise Custom types.
285 ;; We need imenu everywhere because of the predicate index!
296 "Editing and running Prolog and Mercury files."
299 (defgroup prolog-faces nil
300 "Prolog mode specific faces."
303 (defgroup prolog-indentation nil
304 "Prolog mode indentation configuration."
307 (defgroup prolog-font-lock nil
308 "Prolog mode font locking patterns."
311 (defgroup prolog-keyboard nil
312 "Prolog mode keyboard flags."
315 (defgroup prolog-inferior nil
316 "Inferior Prolog mode options."
319 (defgroup prolog-other nil
320 "Other Prolog mode options."
324 ;;-------------------------------------------------------------------
325 ;; User configurable variables
326 ;;-------------------------------------------------------------------
328 ;; General configuration
330 (defcustom prolog-system nil
331 "Prolog interpreter/compiler used.
332 The value of this variable is nil or a symbol.
333 If it is a symbol, it determines default values of other configuration
334 variables with respect to properties of the specified Prolog
335 interpreter/compiler.
337 Currently recognized symbol values are:
338 eclipse - Eclipse Prolog
340 sicstus - SICStus Prolog
345 :type
'(choice (const :tag
"SICStus" :value sicstus
)
346 (const :tag
"SWI Prolog" :value swi
)
347 (const :tag
"GNU Prolog" :value gnu
)
348 (const :tag
"ECLiPSe Prolog" :value eclipse
)
349 ;; Mercury shouldn't be needed since we have a separate
350 ;; major mode for it.
351 (const :tag
"Default" :value nil
)))
352 (make-variable-buffer-local 'prolog-system
)
354 ;; NB: This alist can not be processed in prolog-mode-variables to
355 ;; create a prolog-system-version-i variable since it is needed
356 ;; prior to the call to prolog-mode-variables.
357 (defcustom prolog-system-version
363 ;; FIXME: This should be auto-detected instead of user-provided.
364 "Alist of Prolog system versions.
365 The version numbers are of the format (Major . Minor)."
367 :type
'(repeat (list (symbol :tag
"System")
368 (cons :tag
"Version numbers" (integer :tag
"Major")
369 (integer :tag
"Minor"))))
374 (defcustom prolog-indent-width
4
375 "The indentation width used by the editing buffer."
376 :group
'prolog-indentation
379 (defcustom prolog-left-indent-regexp
"\\(;\\|\\*?->\\)"
380 "Regexp for `prolog-electric-if-then-else-flag'."
382 :group
'prolog-indentation
385 (defcustom prolog-paren-indent-p nil
386 "If non-nil, increase indentation for parenthesis expressions.
387 The second and subsequent line in a parenthesis expression other than
388 a compound term can either be indented `prolog-paren-indent' to the
389 right (if this variable is non-nil) or in the same way as for compound
390 terms (if this variable is nil, default)."
392 :group
'prolog-indentation
395 (defcustom prolog-paren-indent
4
396 "The indentation increase for parenthesis expressions.
397 Only used in ( If -> Then ; Else) and ( Disj1 ; Disj2 ) style expressions."
399 :group
'prolog-indentation
402 (defcustom prolog-parse-mode
'beg-of-clause
403 "The parse mode used (decides from which point parsing is done).
405 `beg-of-line' - starts parsing at the beginning of a line, unless the
406 previous line ends with a backslash. Fast, but has
407 problems detecting multiline /* */ comments.
408 `beg-of-clause' - starts parsing at the beginning of the current clause.
409 Slow, but copes better with /* */ comments."
411 :group
'prolog-indentation
412 :type
'(choice (const :value beg-of-line
)
413 (const :value beg-of-clause
)))
417 (defcustom prolog-keywords
419 ("use_module" "begin_module" "module_interface" "dynamic"
420 "external" "export" "dbgcomp" "nodbgcomp" "compile"))
422 ("all" "else" "end_module" "equality" "external" "fail" "func" "if"
423 "implementation" "import_module" "include_module" "inst" "instance"
424 "interface" "mode" "module" "not" "pragma" "pred" "some" "then" "true"
425 "type" "typeclass" "use_module" "where"))
427 ("block" "dynamic" "mode" "module" "multifile" "meta_predicate"
428 "parallel" "public" "sequential" "volatile"))
430 ("discontiguous" "dynamic" "ensure_loaded" "export" "export_list" "import"
431 "meta_predicate" "module" "module_transparent" "multifile" "require"
432 "use_module" "volatile"))
434 ("built_in" "char_conversion" "discontiguous" "dynamic" "ensure_linked"
435 "ensure_loaded" "foreign" "include" "initialization" "multifile" "op"
436 "public" "set_prolog_flag"))
438 ;; FIXME: Shouldn't we just use the union of all the above here?
439 ("dynamic" "module")))
440 "Alist of Prolog keywords which is used for font locking of directives."
442 :group
'prolog-font-lock
445 (defcustom prolog-types
447 ("char" "float" "int" "io__state" "string" "univ"))
449 "Alist of Prolog types used by font locking."
451 :group
'prolog-font-lock
454 (defcustom prolog-mode-specificators
456 ("bound" "di" "free" "ground" "in" "mdi" "mui" "muo" "out" "ui" "uo"))
458 "Alist of Prolog mode specificators used by font locking."
460 :group
'prolog-font-lock
463 (defcustom prolog-determinism-specificators
465 ("cc_multi" "cc_nondet" "det" "erroneous" "failure" "multi" "nondet"
468 "Alist of Prolog determinism specificators used by font locking."
470 :group
'prolog-font-lock
473 (defcustom prolog-directives
477 "Alist of Prolog source code directives used by font locking."
479 :group
'prolog-font-lock
485 (defcustom prolog-hungry-delete-key-flag nil
486 "Non-nil means delete key consumes all preceding spaces."
488 :group
'prolog-keyboard
491 (defcustom prolog-electric-dot-flag nil
492 "Non-nil means make dot key electric.
493 Electric dot appends newline or inserts head of a new clause.
494 If dot is pressed at the end of a line where at least one white space
495 precedes the point, it inserts a recursive call to the current predicate.
496 If dot is pressed at the beginning of an empty line, it inserts the head
497 of a new clause for the current predicate. It does not apply in strings
499 It does not apply in strings and comments."
501 :group
'prolog-keyboard
504 (defcustom prolog-electric-dot-full-predicate-template nil
505 "If nil, electric dot inserts only the current predicate's name and `('
506 for recursive calls or new clause heads. Non-nil means to also
507 insert enough commas to cover the predicate's arity and `)',
508 and dot and newline for recursive calls."
510 :group
'prolog-keyboard
513 (defcustom prolog-electric-underscore-flag nil
514 "Non-nil means make underscore key electric.
515 Electric underscore replaces the current variable with underscore.
516 If underscore is pressed not on a variable then it behaves as usual."
518 :group
'prolog-keyboard
521 (defcustom prolog-electric-if-then-else-flag nil
522 "Non-nil makes `(', `>' and `;' electric
523 to automatically indent if-then-else constructs."
525 :group
'prolog-keyboard
528 (defcustom prolog-electric-colon-flag nil
529 "Makes `:' electric (inserts `:-' on a new line).
530 If non-nil, pressing `:' at the end of a line that starts in
531 the first column (i.e., clause heads) inserts ` :-' and newline."
533 :group
'prolog-keyboard
536 (defcustom prolog-electric-dash-flag nil
537 "Makes `-' electric (inserts a `-->' on a new line).
538 If non-nil, pressing `-' at the end of a line that starts in
539 the first column (i.e., DCG heads) inserts ` -->' and newline."
541 :group
'prolog-keyboard
544 (defcustom prolog-old-sicstus-keys-flag nil
545 "Non-nil means old SICStus Prolog mode keybindings are used."
547 :group
'prolog-keyboard
552 (defcustom prolog-program-name
553 `(((getenv "EPROLOG") (eval (getenv "EPROLOG")))
557 (swi ,(if (not (executable-find "swipl")) "pl" "swipl"))
559 (t ,(let ((names '("prolog" "gprolog" "swipl" "pl")))
561 (not (executable-find (car names
))))
562 (setq names
(cdr names
)))
563 (or (car names
) "prolog"))))
564 "Alist of program names for invoking an inferior Prolog with `run-prolog'."
565 :group
'prolog-inferior
567 (defun prolog-program-name ()
568 (prolog-find-value-by-system prolog-program-name
))
570 (defcustom prolog-program-switches
573 "Alist of switches given to inferior Prolog run with `run-prolog'."
575 :group
'prolog-inferior
577 (defun prolog-program-switches ()
578 (prolog-find-value-by-system prolog-program-switches
))
580 (defcustom prolog-consult-string
583 (sicstus (eval (if (prolog-atleast-version '(3 .
7))
584 "prolog:zap_file(%m,%b,consult,%l)."
585 "prolog:zap_file(%m,%b,consult).")))
588 (t "reconsult(%f)."))
589 "Alist of strings defining predicate for reconsulting.
591 Some parts of the string are replaced:
592 `%f' by the name of the consulted file (can be a temporary file)
593 `%b' by the file name of the buffer to consult
594 `%m' by the module name and name of the consulted file separated by colon
595 `%l' by the line offset into the file. This is 0 unless consulting a
596 region of a buffer, in which case it is the number of lines before
598 :group
'prolog-inferior
600 (defun prolog-consult-string ()
601 (prolog-find-value-by-system prolog-consult-string
))
603 (defcustom prolog-compile-string
606 (sicstus (eval (if (prolog-atleast-version '(3 .
7))
607 "prolog:zap_file(%m,%b,compile,%l)."
608 "prolog:zap_file(%m,%b,compile).")))
611 "Alist of strings and lists defining predicate for recompilation.
613 Some parts of the string are replaced:
614 `%f' by the name of the compiled file (can be a temporary file)
615 `%b' by the file name of the buffer to compile
616 `%m' by the module name and name of the compiled file separated by colon
617 `%l' by the line offset into the file. This is 0 unless compiling a
618 region of a buffer, in which case it is the number of lines before
621 If `prolog-program-name' is non-nil, it is a string sent to a Prolog process.
622 If `prolog-program-name' is nil, it is an argument to the `compile' function."
623 :group
'prolog-inferior
625 (defun prolog-compile-string ()
626 (prolog-find-value-by-system prolog-compile-string
))
628 (defcustom prolog-eof-string
"end_of_file.\n"
629 "Alist of strings that represent end of file for prolog.
630 nil means send actual operating system end of file."
631 :group
'prolog-inferior
634 (defcustom prolog-prompt-regexp
635 '((eclipse "^[a-zA-Z0-9()]* *\\?- \\|^\\[[a-zA-Z]* [0-9]*\\]:")
636 (sicstus "| [ ?][- ] *")
637 (swi "^\\(\\[[a-zA-Z]*\\] \\)?[1-9]?[0-9]*[ ]?\\?- \\|^| +")
640 "Alist of prompts of the prolog system command line."
642 :group
'prolog-inferior
644 (defun prolog-prompt-regexp ()
645 (prolog-find-value-by-system prolog-prompt-regexp
))
647 ;; (defcustom prolog-continued-prompt-regexp
648 ;; '((sicstus "^\\(| +\\| +\\)")
650 ;; "Alist of regexps matching the prompt when consulting `user'."
651 ;; :group 'prolog-inferior
654 (defcustom prolog-debug-on-string
"debug.\n"
655 "Predicate for enabling debug mode."
657 :group
'prolog-inferior
660 (defcustom prolog-debug-off-string
"nodebug.\n"
661 "Predicate for disabling debug mode."
663 :group
'prolog-inferior
666 (defcustom prolog-trace-on-string
"trace.\n"
667 "Predicate for enabling tracing."
669 :group
'prolog-inferior
672 (defcustom prolog-trace-off-string
"notrace.\n"
673 "Predicate for disabling tracing."
675 :group
'prolog-inferior
678 (defcustom prolog-zip-on-string
"zip.\n"
679 "Predicate for enabling zip mode for SICStus."
681 :group
'prolog-inferior
684 (defcustom prolog-zip-off-string
"nozip.\n"
685 "Predicate for disabling zip mode for SICStus."
687 :group
'prolog-inferior
690 (defcustom prolog-use-standard-consult-compile-method-flag t
691 "Non-nil means use the standard compilation method.
692 Otherwise the new compilation method will be used. This
693 utilizes a special compilation buffer with the associated
694 features such as parsing of error messages and automatically
695 jumping to the source code responsible for the error.
697 Warning: the new method is so far only experimental and
698 does contain bugs. The recommended setting for the novice user
699 is non-nil for this variable."
701 :group
'prolog-inferior
707 (defcustom prolog-imenu-flag t
708 "Non-nil means add a clause index menu for all prolog files."
713 (defcustom prolog-imenu-max-lines
3000
714 "The maximum number of lines of the file for imenu to be enabled.
715 Relevant only when `prolog-imenu-flag' is non-nil."
720 (defcustom prolog-info-predicate-index
721 "(sicstus)Predicate Index"
722 "The info node for the SICStus predicate index."
727 (defcustom prolog-underscore-wordchar-flag nil
728 "Non-nil means underscore (_) is a word-constituent character."
732 (make-obsolete-variable 'prolog-underscore-wordchar-flag
733 'superword-mode
"24.4")
735 (defcustom prolog-use-sicstus-sd nil
736 "If non-nil, use the source level debugger of SICStus 3#7 and later."
741 (defcustom prolog-char-quote-workaround nil
742 "If non-nil, declare 0 as a quote character to handle 0'<char>.
743 This is really kludgy, and unneeded (i.e. obsolete) in Emacs>=24."
747 (make-obsolete-variable 'prolog-char-quote-workaround nil
"24.1")
750 ;;-------------------------------------------------------------------
751 ;; Internal variables
752 ;;-------------------------------------------------------------------
754 ;;(defvar prolog-temp-filename "") ; Later set by `prolog-temporary-file'
756 (defvar prolog-mode-syntax-table
757 ;; The syntax accepted varies depending on the implementation used.
758 ;; Here are some of the differences:
759 ;; - SWI-Prolog accepts nested /*..*/ comments.
760 ;; - Edinburgh-style Prologs take <radix>'<number> for non-decimal number,
761 ;; whereas ISO-style Prologs use 0[obx]<number> instead.
762 ;; - In atoms \x<hex> sometimes needs a terminating \ (ISO-style)
763 ;; and sometimes not.
764 (let ((table (make-syntax-table)))
765 (modify-syntax-entry ?_
(if prolog-underscore-wordchar-flag
"w" "_") table
)
766 (modify-syntax-entry ?
+ "." table
)
767 (modify-syntax-entry ?-
"." table
)
768 (modify-syntax-entry ?
= "." table
)
769 (modify-syntax-entry ?
< "." table
)
770 (modify-syntax-entry ?
> "." table
)
771 (modify-syntax-entry ?|
"." table
)
772 (modify-syntax-entry ?
\' "\"" table
)
774 ;; Any better way to handle the 0'<char> construct?!?
775 (when (and prolog-char-quote-workaround
776 (not (fboundp 'syntax-propertize-rules
)))
777 (modify-syntax-entry ?
0 "\\" table
))
779 (modify-syntax-entry ?%
"<" table
)
780 (modify-syntax-entry ?
\n ">" table
)
781 (if (featurep 'xemacs
)
783 (modify-syntax-entry ?
* ". 67" table
)
784 (modify-syntax-entry ?
/ ". 58" table
)
786 ;; Emacs wants to see this it seems:
787 (modify-syntax-entry ?
* ". 23b" table
)
788 (modify-syntax-entry ?
/ ". 14" table
)
792 (defconst prolog-atom-char-regexp
794 "Regexp specifying characters which constitute atoms without quoting.")
795 (defconst prolog-atom-regexp
796 (format "[[:lower:]$]%s*" prolog-atom-char-regexp
))
798 (defconst prolog-left-paren
"[[({]" ;FIXME: Why not \\s(?
799 "The characters used as left parentheses for the indentation code.")
800 (defconst prolog-right-paren
"[])}]" ;FIXME: Why not \\s)?
801 "The characters used as right parentheses for the indentation code.")
803 (defconst prolog-quoted-atom-regexp
804 "\\(^\\|[^0-9]\\)\\('\\([^\n']\\|\\\\'\\)*'\\)"
805 "Regexp matching a quoted atom.")
806 (defconst prolog-string-regexp
807 "\\(\"\\([^\n\"]\\|\\\\\"\\)*\"\\)"
808 "Regexp matching a string.")
809 (defconst prolog-head-delimiter
"\\(:-\\|\\+:\\|-:\\|\\+\\?\\|-\\?\\|-->\\)"
810 "A regexp for matching on the end delimiter of a head (e.g. \":-\").")
812 (defvar prolog-compilation-buffer
"*prolog-compilation*"
813 "Name of the output buffer for Prolog compilation/consulting.")
815 (defvar prolog-temporary-file-name nil
)
816 (defvar prolog-keywords-i nil
)
817 (defvar prolog-types-i nil
)
818 (defvar prolog-mode-specificators-i nil
)
819 (defvar prolog-determinism-specificators-i nil
)
820 (defvar prolog-directives-i nil
)
821 (defvar prolog-eof-string-i nil
)
822 ;; (defvar prolog-continued-prompt-regexp-i nil)
823 (defvar prolog-help-function-i nil
)
825 (defvar prolog-align-rules
831 `(,(intern (format "prolog-%s" name
))
832 (regexp .
,(format "\\(\\s-*\\)%s\\(\\s-*\\)" sym
))
834 (modes .
'(prolog-mode))
836 '(("dcg" .
"-->") ("rule" .
":-") ("simplification" .
"<=>")
837 ("propagation" .
"==>")))))
843 (defun prolog-smie-forward-token ()
844 ;; FIXME: Add support for 0'<char>, if needed after adding it to
845 ;; syntax-propertize-functions.
846 (forward-comment (point-max))
847 (buffer-substring-no-properties
850 ((looking-at "[!;]") (forward-char 1))
851 ((not (zerop (skip-chars-forward "#&*+-./:<=>?@\\^`~"))))
852 ((not (zerop (skip-syntax-forward "w_'"))))
853 ;; In case of non-ASCII punctuation.
854 ((not (zerop (skip-syntax-forward ".")))))
857 (defun prolog-smie-backward-token ()
858 ;; FIXME: Add support for 0'<char>, if needed after adding it to
859 ;; syntax-propertize-functions.
860 (forward-comment (- (point-max)))
861 (buffer-substring-no-properties
864 ((memq (char-before) '(?
! ?\
;)) (forward-char -1))
865 ((not (zerop (skip-chars-backward "#&*+-./:<=>?@\\^`~"))))
866 ((not (zerop (skip-syntax-backward "w_'"))))
867 ;; In case of non-ASCII punctuation.
868 ((not (zerop (skip-syntax-backward ".")))))
871 (defconst prolog-smie-grammar
872 ;; Rather than construct the operator levels table from the BNF,
873 ;; we directly provide the operator precedences from GNU Prolog's
874 ;; manual (7.14.10 op/3). The only problem is that GNU Prolog's
875 ;; manual uses precedence levels in the opposite sense (higher
876 ;; numbers bind less tightly) than SMIE, so we use negative numbers.
877 '(("." -
10000 -
10000)
918 (:smie-closer-alist
(t .
"."))
920 "Precedence levels of infix operators.")
922 (defun prolog-smie-rules (kind token
)
923 (pcase (cons kind token
)
924 (`(:elem . basic
) prolog-indent-width
)
925 (`(:after .
".") '(column .
0)) ;; To work around smie-closer-alist.
926 ;; Allow indentation of if-then-else as:
931 (`(:before .
,(or `"->" `";"))
932 (and (smie-rule-bolp) (smie-rule-parent-p "(") (smie-rule-parent 0)))
933 (`(:after .
,(or `"->" `"*->"))
944 ;; based on the space between the open paren and the "a".
945 (unless (and (smie-rule-parent-p "(")
947 (smie-indent-forward-token)
948 (smie-backward-sexp 'halfsexp
)
949 (not (eq ?\
( (char-before)))))
950 prolog-indent-width
))
951 (`(:after .
,(or `":-" `"-->")) prolog-indent-width
)))
954 ;;-------------------------------------------------------------------
956 ;;-------------------------------------------------------------------
958 ;; Example: (prolog-atleast-version '(3 . 6))
959 (defun prolog-atleast-version (version)
960 "Return t if the version of the current prolog system is VERSION or later.
961 VERSION is of the format (Major . Minor)"
962 ;; Version.major < major or
963 ;; Version.major = major and Version.minor <= minor
964 (let* ((thisversion (prolog-find-value-by-system prolog-system-version
))
965 (thismajor (car thisversion
))
966 (thisminor (cdr thisversion
)))
967 (or (< (car version
) thismajor
)
968 (and (= (car version
) thismajor
)
969 (<= (cdr version
) thisminor
)))
972 (define-abbrev-table 'prolog-mode-abbrev-table
())
974 (defun prolog-find-value-by-system (alist)
975 "Get value from ALIST according to `prolog-system'."
976 (let ((system (or prolog-system
977 (let ((infbuf (prolog-inferior-buffer 'dont-run
)))
979 (buffer-local-value 'prolog-system infbuf
))))))
984 (setq id
(car (car alist
)))
985 (if (or (eq id system
)
990 (setq result
(car (cdr (car alist
))))
991 (if (and (listp result
)
992 (eq (car result
) 'eval
))
993 (setq result
(eval (car (cdr result
)))))
995 (setq alist
(cdr alist
))))
999 (defconst prolog-syntax-propertize-function
1000 (when (fboundp 'syntax-propertize-rules
)
1001 (syntax-propertize-rules
1002 ;; GNU Prolog only accepts 0'\' rather than 0'', but the only
1003 ;; possible meaning of 0'' is rather clear.
1005 (1 (unless (save-excursion (nth 8 (syntax-ppss (match-beginning 0))))
1006 (string-to-syntax "_"))))
1007 ;; We could check that we're not inside an atom, but I don't think
1008 ;; that 'foo 8'z could be a valid syntax anyway, so why bother?
1009 ("\\<[1-9][0-9]*\\('\\)[0-9a-zA-Z]" (1 "_"))
1010 ;; Supposedly, ISO-Prolog wants \NNN\ for octal and \xNNN\ for hexadecimal
1011 ;; escape sequences in atoms, so be careful not to let the terminating \
1012 ;; escape a subsequent quote.
1013 ("\\\\[x0-7][0-9a-fA-F]*\\(\\\\\\)" (1 "_"))
1016 (defun prolog-mode-variables ()
1017 "Set some common variables to Prolog code specific values."
1018 (setq-local local-abbrev-table prolog-mode-abbrev-table
)
1019 (setq-local paragraph-start
(concat "[ \t]*$\\|" page-delimiter
)) ;'%%..'
1020 (setq-local paragraph-separate paragraph-start
)
1021 (setq-local paragraph-ignore-fill-prefix t
)
1022 (setq-local normal-auto-fill-function
'prolog-do-auto-fill
)
1023 (setq-local comment-start
"%")
1024 (setq-local comment-end
"")
1025 (setq-local comment-add
1)
1026 (setq-local comment-start-skip
"\\(?:/\\*+ *\\|%%+ *\\)")
1027 (setq-local parens-require-spaces nil
)
1028 ;; Initialize Prolog system specific variables
1029 (dolist (var '(prolog-keywords prolog-types prolog-mode-specificators
1030 prolog-determinism-specificators prolog-directives
1032 ;; prolog-continued-prompt-regexp
1033 prolog-help-function
))
1034 (set (intern (concat (symbol-name var
) "-i"))
1035 (prolog-find-value-by-system (symbol-value var
))))
1036 (when (null (prolog-program-name))
1037 (setq-local compile-command
(prolog-compile-string)))
1038 (setq-local font-lock-defaults
1039 '(prolog-font-lock-keywords nil nil
((?_ .
"w"))))
1040 (setq-local syntax-propertize-function prolog-syntax-propertize-function
)
1042 (smie-setup prolog-smie-grammar
#'prolog-smie-rules
1043 :forward-token
#'prolog-smie-forward-token
1044 :backward-token
#'prolog-smie-backward-token
))
1046 (defun prolog-mode-keybindings-common (map)
1047 "Define keybindings common to both Prolog modes in MAP."
1048 (define-key map
"\C-c?" 'prolog-help-on-predicate
)
1049 (define-key map
"\C-c/" 'prolog-help-apropos
)
1050 (define-key map
"\C-c\C-d" 'prolog-debug-on
)
1051 (define-key map
"\C-c\C-t" 'prolog-trace-on
)
1052 (define-key map
"\C-c\C-z" 'prolog-zip-on
)
1053 (define-key map
"\C-c\r" 'run-prolog
))
1055 (defun prolog-mode-keybindings-edit (map)
1056 "Define keybindings for Prolog mode in MAP."
1057 (define-key map
"\M-a" 'prolog-beginning-of-clause
)
1058 (define-key map
"\M-e" 'prolog-end-of-clause
)
1059 (define-key map
"\M-q" 'prolog-fill-paragraph
)
1060 (define-key map
"\C-c\C-a" 'align
)
1061 (define-key map
"\C-\M-a" 'prolog-beginning-of-predicate
)
1062 (define-key map
"\C-\M-e" 'prolog-end-of-predicate
)
1063 (define-key map
"\M-\C-c" 'prolog-mark-clause
)
1064 (define-key map
"\M-\C-h" 'prolog-mark-predicate
)
1065 (define-key map
"\C-c\C-n" 'prolog-insert-predicate-template
)
1066 (define-key map
"\C-c\C-s" 'prolog-insert-predspec
)
1067 (define-key map
"\M-\r" 'prolog-insert-next-clause
)
1068 (define-key map
"\C-c\C-va" 'prolog-variables-to-anonymous
)
1069 (define-key map
"\C-c\C-v\C-s" 'prolog-view-predspec
)
1071 ;; If we're running SICStus, then map C-c C-c e/d to enabling
1072 ;; and disabling of the source-level debugging facilities.
1073 ;(if (and (eq prolog-system 'sicstus)
1074 ; (prolog-atleast-version '(3 . 7)))
1076 ; (define-key map "\C-c\C-ce" 'prolog-enable-sicstus-sd)
1077 ; (define-key map "\C-c\C-cd" 'prolog-disable-sicstus-sd)
1080 (if prolog-old-sicstus-keys-flag
1082 (define-key map
"\C-c\C-c" 'prolog-consult-predicate
)
1083 (define-key map
"\C-cc" 'prolog-consult-region
)
1084 (define-key map
"\C-cC" 'prolog-consult-buffer
)
1085 (define-key map
"\C-c\C-k" 'prolog-compile-predicate
)
1086 (define-key map
"\C-ck" 'prolog-compile-region
)
1087 (define-key map
"\C-cK" 'prolog-compile-buffer
))
1088 (define-key map
"\C-c\C-p" 'prolog-consult-predicate
)
1089 (define-key map
"\C-c\C-r" 'prolog-consult-region
)
1090 (define-key map
"\C-c\C-b" 'prolog-consult-buffer
)
1091 (define-key map
"\C-c\C-f" 'prolog-consult-file
)
1092 (define-key map
"\C-c\C-cp" 'prolog-compile-predicate
)
1093 (define-key map
"\C-c\C-cr" 'prolog-compile-region
)
1094 (define-key map
"\C-c\C-cb" 'prolog-compile-buffer
)
1095 (define-key map
"\C-c\C-cf" 'prolog-compile-file
))
1097 ;; Inherited from the old prolog.el.
1098 (define-key map
"\e\C-x" 'prolog-consult-region
)
1099 (define-key map
"\C-c\C-l" 'prolog-consult-file
)
1100 (define-key map
"\C-c\C-z" 'run-prolog
))
1102 (defun prolog-mode-keybindings-inferior (_map)
1103 "Define keybindings for inferior Prolog mode in MAP."
1104 ;; No inferior mode specific keybindings now.
1107 (defvar prolog-mode-map
1108 (let ((map (make-sparse-keymap)))
1109 (prolog-mode-keybindings-common map
)
1110 (prolog-mode-keybindings-edit map
)
1114 (defvar prolog-mode-hook nil
1115 "List of functions to call after the prolog mode has initialized.")
1118 (define-derived-mode prolog-mode prog-mode
"Prolog"
1119 "Major mode for editing Prolog code.
1121 Blank lines and `%%...' separate paragraphs. `%'s starts a comment
1122 line and comments can also be enclosed in /* ... */.
1124 If an optional argument SYSTEM is non-nil, set up mode for the given system.
1126 To find out what version of Prolog mode you are running, enter
1127 `\\[prolog-mode-version]'.
1130 \\{prolog-mode-map}"
1131 (setq mode-name
(concat "Prolog"
1133 ((eq prolog-system
'eclipse
) "[ECLiPSe]")
1134 ((eq prolog-system
'sicstus
) "[SICStus]")
1135 ((eq prolog-system
'swi
) "[SWI]")
1136 ((eq prolog-system
'gnu
) "[GNU]")
1138 (prolog-mode-variables)
1139 (dolist (ar prolog-align-rules
) (add-to-list 'align-rules-list ar
))
1140 (add-hook 'post-self-insert-hook
#'prolog-post-self-insert nil t
)
1141 ;; `imenu' entry moved to the appropriate hook for consistency.
1142 (when prolog-electric-dot-flag
1143 (setq-local electric-indent-chars
1144 (cons ?\. electric-indent-chars
)))
1146 ;; Load SICStus debugger if suitable
1147 (if (and (eq prolog-system
'sicstus
)
1148 (prolog-atleast-version '(3 .
7))
1149 prolog-use-sicstus-sd
)
1150 (prolog-enable-sicstus-sd))
1154 (defvar mercury-mode-map
1155 (let ((map (make-sparse-keymap)))
1156 (set-keymap-parent map prolog-mode-map
)
1160 (define-derived-mode mercury-mode prolog-mode
"Prolog[Mercury]"
1161 "Major mode for editing Mercury programs.
1162 Actually this is just customized `prolog-mode'."
1163 (setq-local prolog-system
'mercury
))
1166 ;;-------------------------------------------------------------------
1167 ;; Inferior prolog mode
1168 ;;-------------------------------------------------------------------
1170 (defvar prolog-inferior-mode-map
1171 (let ((map (make-sparse-keymap)))
1172 (prolog-mode-keybindings-common map
)
1173 (prolog-mode-keybindings-inferior map
)
1174 (define-key map
[remap self-insert-command
]
1175 'prolog-inferior-self-insert-command
)
1178 (defvar prolog-inferior-mode-hook nil
1179 "List of functions to call after the inferior prolog mode has initialized.")
1181 (defvar prolog-inferior-error-regexp-alist
1182 '(;; GNU Prolog used to not follow the GNU standard format.
1183 ;; ("^\\(.*?\\):\\([0-9]+\\) error: .*(char:\\([0-9]+\\)" 1 2 3)
1185 ("^\\(?:\\?- *\\)?\\(\\(?:ERROR\\|\\(W\\)arning\\): *\\(.*?\\):\\([1-9][0-9]*\\):\\(?:\\([0-9]*\\):\\)?\\)\\(?:$\\| \\)"
1187 ;; GNU-Prolog now uses the GNU standard format.
1190 (defun prolog-inferior-self-insert-command ()
1191 "Insert the char in the buffer or pass it directly to the process."
1193 (let* ((proc (get-buffer-process (current-buffer)))
1194 (pmark (and proc
(marker-position (process-mark proc
)))))
1195 ;; FIXME: the same treatment would be needed for SWI-Prolog, but I can't
1196 ;; seem to find any way for Emacs to figure out when to use it because
1197 ;; SWI doesn't include a " ? " or some such recognizable marker.
1198 (if (and (eq prolog-system
'gnu
)
1200 (null current-prefix-arg
)
1204 (goto-char (- pmark
3))
1205 ;; FIXME: check this comes from the process's output, maybe?
1206 (looking-at " \\? ")))
1207 ;; This is GNU prolog waiting to know whether you want more answers
1208 ;; or not (or abort, etc...). The answer is a single char, not
1209 ;; a line, so pass this char directly rather than wait for RET to
1210 ;; send a whole line.
1211 (comint-send-string proc
(string last-command-event
))
1212 (call-interactively 'self-insert-command
))))
1214 (declare-function 'compilation-shell-minor-mode
"compile" (&optional arg
))
1215 (defvar compilation-error-regexp-alist
)
1217 (define-derived-mode prolog-inferior-mode comint-mode
"Inferior Prolog"
1218 "Major mode for interacting with an inferior Prolog process.
1220 The following commands are available:
1221 \\{prolog-inferior-mode-map}
1223 Entry to this mode calls the value of `prolog-mode-hook' with no arguments,
1224 if that value is non-nil. Likewise with the value of `comint-mode-hook'.
1225 `prolog-mode-hook' is called after `comint-mode-hook'.
1227 You can send text to the inferior Prolog from other buffers
1228 using the commands `send-region', `send-string' and \\[prolog-consult-region].
1231 Tab indents for Prolog; with argument, shifts rest
1232 of expression rigidly with the current line.
1233 Paragraphs are separated only by blank lines and `%%'. `%'s start comments.
1235 Return at end of buffer sends line as input.
1236 Return not at end copies rest of line to end and sends it.
1237 \\[comint-delchar-or-maybe-eof] sends end-of-file as input.
1238 \\[comint-kill-input] and \\[backward-kill-word] are kill commands,
1239 imitating normal Unix input editing.
1240 \\[comint-interrupt-subjob] interrupts the shell or its current subjob if any.
1241 \\[comint-stop-subjob] stops, likewise.
1242 \\[comint-quit-subjob] sends quit signal, likewise.
1244 To find out what version of Prolog mode you are running, enter
1245 `\\[prolog-mode-version]'."
1247 (setq comint-input-filter
'prolog-input-filter
)
1248 (setq mode-line-process
'(": %s"))
1249 (prolog-mode-variables)
1250 (setq comint-prompt-regexp
(prolog-prompt-regexp))
1251 (setq-local shell-dirstack-query
"pwd.")
1252 (setq-local compilation-error-regexp-alist
1253 prolog-inferior-error-regexp-alist
)
1254 (compilation-shell-minor-mode)
1255 (prolog-inferior-menu))
1257 (defun prolog-input-filter (str)
1258 (cond ((string-match "\\`\\s *\\'" str
) nil
) ;whitespace
1259 ((not (derived-mode-p 'prolog-inferior-mode
)) t
)
1260 ((= (length str
) 1) nil
) ;one character
1261 ((string-match "\\`[rf] *[0-9]*\\'" str
) nil
) ;r(edo) or f(ail)
1264 ;; This statement was missing in Emacs 24.1, 24.2, 24.3.
1265 (define-obsolete-function-alias 'switch-to-prolog
'run-prolog
"24.1")
1267 (defun run-prolog (arg)
1268 "Run an inferior Prolog process, input and output via buffer *prolog*.
1269 With prefix argument ARG, restart the Prolog process if running before."
1271 ;; FIXME: It should be possible to interactively specify the command to use
1273 (if (and arg
(get-process "prolog"))
1275 (process-send-string "prolog" "halt.\n")
1276 (while (get-process "prolog") (sit-for 0.1))))
1277 (let ((buff (buffer-name)))
1278 (if (not (string= buff
"*prolog*"))
1279 (prolog-goto-prolog-process-buffer))
1280 ;; Load SICStus debugger if suitable
1281 (if (and (eq prolog-system
'sicstus
)
1282 (prolog-atleast-version '(3 .
7))
1283 prolog-use-sicstus-sd
)
1284 (prolog-enable-sicstus-sd))
1285 (prolog-mode-variables)
1286 (prolog-ensure-process)
1289 (defun prolog-inferior-guess-flavor (&optional ignored
)
1290 (setq-local prolog-system
1291 (when (or (numberp prolog-system
) (markerp prolog-system
))
1293 (goto-char (1+ prolog-system
))
1295 ((looking-at "GNU Prolog") 'gnu
)
1296 ((looking-at "Welcome to SWI-Prolog\\|%.*\\<swi_") 'swi
)
1297 ((looking-at ".*\n") nil
) ;There's at least one line.
1298 (t prolog-system
)))))
1299 (when (symbolp prolog-system
)
1300 (remove-hook 'comint-output-filter-functions
1301 'prolog-inferior-guess-flavor t
)
1303 (setq comint-prompt-regexp
(prolog-prompt-regexp))
1304 (if (eq prolog-system
'gnu
)
1305 (setq-local comint-process-echoes t
)))))
1307 (defun prolog-ensure-process (&optional wait
)
1308 "If Prolog process is not running, run it.
1309 If the optional argument WAIT is non-nil, wait for Prolog prompt specified by
1310 the variable `prolog-prompt-regexp'."
1311 (if (null (prolog-program-name))
1312 (error "This Prolog system has defined no interpreter."))
1313 (if (comint-check-proc "*prolog*")
1315 (with-current-buffer (get-buffer-create "*prolog*")
1316 (prolog-inferior-mode)
1317 (apply 'make-comint-in-buffer
"prolog" (current-buffer)
1318 (prolog-program-name) nil
(prolog-program-switches))
1319 (unless prolog-system
1320 ;; Setup auto-detection.
1323 ;; Force re-detection.
1324 (let* ((proc (get-buffer-process (current-buffer)))
1325 (pmark (and proc
(marker-position (process-mark proc
)))))
1327 ((null pmark
) (1- (point-min)))
1328 ;; The use of insert-before-markers in comint.el together with
1329 ;; the potential use of comint-truncate-buffer in the output
1330 ;; filter, means that it's difficult to reliably keep track of
1331 ;; the buffer position where the process's output started.
1332 ;; If possible we use a marker at "start - 1", so that
1333 ;; insert-before-marker at `start' won't shift it. And if not,
1334 ;; we fall back on using a plain integer.
1335 ((> pmark
(point-min)) (copy-marker (1- pmark
)))
1337 (add-hook 'comint-output-filter-functions
1338 'prolog-inferior-guess-flavor nil t
))
1341 (goto-char (point-max))
1346 (concat "\\(" (prolog-prompt-regexp) "\\)" "\\=")
1350 (defun prolog-inferior-buffer (&optional dont-run
)
1351 (or (get-buffer "*prolog*")
1353 (prolog-ensure-process)
1354 (get-buffer "*prolog*"))))
1356 (defun prolog-process-insert-string (process string
)
1357 "Insert STRING into inferior Prolog buffer running PROCESS."
1358 ;; Copied from elisp manual, greek to me
1359 (with-current-buffer (process-buffer process
)
1360 ;; FIXME: Use window-point-insertion-type instead.
1361 (let ((moving (= (point) (process-mark process
))))
1363 ;; Insert the text, moving the process-marker.
1364 (goto-char (process-mark process
))
1366 (set-marker (process-mark process
) (point)))
1367 (if moving
(goto-char (process-mark process
))))))
1369 ;;------------------------------------------------------------
1370 ;; Old consulting and compiling functions
1371 ;;------------------------------------------------------------
1373 (declare-function compilation-forget-errors
"compile" ())
1374 (declare-function compilation-fake-loc
"compile"
1375 (marker file
&optional line col
))
1377 (defun prolog-old-process-region (compilep start end
)
1378 "Process the region limited by START and END positions.
1379 If COMPILEP is non-nil then use compilation, otherwise consulting."
1380 (prolog-ensure-process)
1381 ;(let ((tmpfile prolog-temp-filename)
1382 (let ((tmpfile (prolog-temporary-file))
1383 ;(process (get-process "prolog"))
1384 (first-line (1+ (count-lines
1389 (write-region start end tmpfile
)
1390 (setq start
(copy-marker start
))
1391 (with-current-buffer (prolog-inferior-buffer)
1392 (compilation-forget-errors)
1393 (compilation-fake-loc start tmpfile
))
1394 (process-send-string
1395 "prolog" (prolog-build-prolog-command
1396 compilep tmpfile
(prolog-bsts buffer-file-name
)
1398 (prolog-goto-prolog-process-buffer)))
1400 (defun prolog-old-process-predicate (compilep)
1401 "Process the predicate around point.
1402 If COMPILEP is non-nil then use compilation, otherwise consulting."
1403 (prolog-old-process-region
1404 compilep
(prolog-pred-start) (prolog-pred-end)))
1406 (defun prolog-old-process-buffer (compilep)
1407 "Process the entire buffer.
1408 If COMPILEP is non-nil then use compilation, otherwise consulting."
1409 (prolog-old-process-region compilep
(point-min) (point-max)))
1411 (defun prolog-old-process-file (compilep)
1412 "Process the file of the current buffer.
1413 If COMPILEP is non-nil then use compilation, otherwise consulting."
1415 (prolog-ensure-process)
1416 (with-current-buffer (prolog-inferior-buffer)
1417 (compilation-forget-errors))
1418 (process-send-string
1419 "prolog" (prolog-build-prolog-command
1420 compilep buffer-file-name
1421 (prolog-bsts buffer-file-name
)))
1422 (prolog-goto-prolog-process-buffer))
1425 ;;------------------------------------------------------------
1426 ;; Consulting and compiling
1427 ;;------------------------------------------------------------
1429 ;; Interactive interface functions, used by both the standard
1430 ;; and the experimental consultation and compilation functions
1431 (defun prolog-consult-file ()
1432 "Consult file of current buffer."
1434 (if prolog-use-standard-consult-compile-method-flag
1435 (prolog-old-process-file nil
)
1436 (prolog-consult-compile-file nil
)))
1438 (defun prolog-consult-buffer ()
1441 (if prolog-use-standard-consult-compile-method-flag
1442 (prolog-old-process-buffer nil
)
1443 (prolog-consult-compile-buffer nil
)))
1445 (defun prolog-consult-region (beg end
)
1446 "Consult region between BEG and END."
1448 (if prolog-use-standard-consult-compile-method-flag
1449 (prolog-old-process-region nil beg end
)
1450 (prolog-consult-compile-region nil beg end
)))
1452 (defun prolog-consult-predicate ()
1453 "Consult the predicate around current point."
1455 (if prolog-use-standard-consult-compile-method-flag
1456 (prolog-old-process-predicate nil
)
1457 (prolog-consult-compile-predicate nil
)))
1459 (defun prolog-compile-file ()
1460 "Compile file of current buffer."
1462 (if prolog-use-standard-consult-compile-method-flag
1463 (prolog-old-process-file t
)
1464 (prolog-consult-compile-file t
)))
1466 (defun prolog-compile-buffer ()
1469 (if prolog-use-standard-consult-compile-method-flag
1470 (prolog-old-process-buffer t
)
1471 (prolog-consult-compile-buffer t
)))
1473 (defun prolog-compile-region (beg end
)
1474 "Compile region between BEG and END."
1476 (if prolog-use-standard-consult-compile-method-flag
1477 (prolog-old-process-region t beg end
)
1478 (prolog-consult-compile-region t beg end
)))
1480 (defun prolog-compile-predicate ()
1481 "Compile the predicate around current point."
1483 (if prolog-use-standard-consult-compile-method-flag
1484 (prolog-old-process-predicate t
)
1485 (prolog-consult-compile-predicate t
)))
1487 (defun prolog-buffer-module ()
1488 "Select Prolog module name appropriate for current buffer.
1489 Bases decision on buffer contents (-*- line)."
1490 ;; Look for -*- ... module: MODULENAME; ... -*-
1493 (goto-char (point-min))
1494 (skip-chars-forward " \t")
1495 (and (search-forward "-*-" (line-end-position) t
)
1497 (skip-chars-forward " \t")
1499 (search-forward "-*-" (line-end-position) t
))
1502 (skip-chars-backward " \t")
1505 (and (let ((case-fold-search t
))
1506 (search-forward "module:" end t
))
1508 (skip-chars-forward " \t")
1510 (if (search-forward ";" end t
)
1513 (skip-chars-backward " \t")
1514 (buffer-substring beg
(point)))))))))
1516 (defun prolog-build-prolog-command (compilep file buffername
1517 &optional first-line
)
1518 "Make Prolog command for FILE compilation/consulting.
1519 If COMPILEP is non-nil, consider compilation, otherwise consulting."
1520 (let* ((compile-string
1521 ;; FIXME: If the process is not running yet, the auto-detection of
1522 ;; prolog-system won't help here, so we should make sure
1523 ;; we first run Prolog and then build the command.
1524 (if compilep
(prolog-compile-string) (prolog-consult-string)))
1525 (module (prolog-buffer-module))
1526 (file-name (concat "'" (prolog-bsts file
) "'"))
1527 (module-name (if module
(concat "'" module
"'")))
1528 (module-file (if module
1529 (concat module-name
":" file-name
)
1532 (lineoffset (if first-line
1536 ;; Assure that there is a buffer name
1537 (if (not buffername
)
1538 (error "The buffer is not saved"))
1540 (if (not (string-match "\\`'.*'\\'" buffername
)) ; Add quotes
1541 (setq buffername
(concat "'" buffername
"'")))
1542 (while (string-match "%m" compile-string
)
1543 (setq strbeg
(substring compile-string
0 (match-beginning 0)))
1544 (setq strend
(substring compile-string
(match-end 0)))
1545 (setq compile-string
(concat strbeg module-file strend
)))
1546 ;; FIXME: The code below will %-expand any %[fbl] that appears in
1548 (while (string-match "%f" compile-string
)
1549 (setq strbeg
(substring compile-string
0 (match-beginning 0)))
1550 (setq strend
(substring compile-string
(match-end 0)))
1551 (setq compile-string
(concat strbeg file-name strend
)))
1552 (while (string-match "%b" compile-string
)
1553 (setq strbeg
(substring compile-string
0 (match-beginning 0)))
1554 (setq strend
(substring compile-string
(match-end 0)))
1555 (setq compile-string
(concat strbeg buffername strend
)))
1556 (while (string-match "%l" compile-string
)
1557 (setq strbeg
(substring compile-string
0 (match-beginning 0)))
1558 (setq strend
(substring compile-string
(match-end 0)))
1559 (setq compile-string
(concat strbeg
(format "%d" lineoffset
) strend
)))
1560 (concat compile-string
"\n")))
1562 ;; The rest of this page is experimental code!
1564 ;; Global variables for process filter function
1565 (defvar prolog-process-flag nil
1566 "Non-nil means that a prolog task (i.e. a consultation or compilation job)
1568 (defvar prolog-consult-compile-output
""
1569 "Hold the unprocessed output from the current prolog task.")
1570 (defvar prolog-consult-compile-first-line
1
1571 "The number of the first line of the file to consult/compile.
1572 Used for temporary files.")
1573 (defvar prolog-consult-compile-file nil
1574 "The file to compile/consult (can be a temporary file).")
1575 (defvar prolog-consult-compile-real-file nil
1576 "The file name of the buffer to compile/consult.")
1578 (defvar compilation-parse-errors-function
)
1580 (defun prolog-consult-compile (compilep file
&optional first-line
)
1581 "Consult/compile FILE.
1582 If COMPILEP is non-nil, perform compilation, otherwise perform CONSULTING.
1583 COMMAND is a string described by the variables `prolog-consult-string'
1584 and `prolog-compile-string'.
1585 Optional argument FIRST-LINE is the number of the first line in the compiled
1588 This function must be called from the source code buffer."
1589 (if prolog-process-flag
1590 (error "Another Prolog task is running."))
1591 (prolog-ensure-process t
)
1592 (let* ((buffer (get-buffer-create prolog-compilation-buffer
))
1593 (real-file buffer-file-name
)
1594 (command-string (prolog-build-prolog-command compilep file
1595 real-file first-line
))
1596 (process (get-process "prolog")))
1597 (with-current-buffer buffer
1598 (delete-region (point-min) (point-max))
1599 ;; FIXME: Wasn't this supposed to use prolog-inferior-mode?
1601 ;; FIXME: This doesn't seem to cooperate well with new(ish) compile.el.
1602 ;; Setting up font-locking for this buffer
1603 (setq-local font-lock-defaults
1604 '(prolog-font-lock-keywords nil nil
((?_ .
"w"))))
1605 (if (eq prolog-system
'sicstus
)
1606 ;; FIXME: This looks really problematic: not only is this using
1607 ;; the old compilation-parse-errors-function, but
1608 ;; prolog-parse-sicstus-compilation-errors only accepts one argument
1609 ;; whereas compile.el calls it with 2 (and did so at least since
1611 (setq-local compilation-parse-errors-function
1612 'prolog-parse-sicstus-compilation-errors
))
1613 (setq buffer-read-only nil
)
1614 (insert command-string
"\n"))
1615 (display-buffer buffer
)
1616 (setq prolog-process-flag t
1617 prolog-consult-compile-output
""
1618 prolog-consult-compile-first-line
(if first-line
(1- first-line
) 0)
1619 prolog-consult-compile-file file
1620 prolog-consult-compile-real-file
(if (string=
1621 file buffer-file-name
)
1624 (with-current-buffer buffer
1625 (goto-char (point-max))
1626 (add-function :override
(process-filter process
)
1627 #'prolog-consult-compile-filter
)
1628 (process-send-string "prolog" command-string
)
1629 ;; (prolog-build-prolog-command compilep file real-file first-line))
1630 (while (and prolog-process-flag
1631 (accept-process-output process
10)) ; 10 secs is ok?
1633 (unless (get-process "prolog")
1634 (setq prolog-process-flag nil
)))
1635 (insert (if compilep
1636 "\nCompilation finished.\n"
1638 (remove-function (process-filter process
)
1639 #'prolog-consult-compile-filter
))))
1641 (defvar compilation-error-list
)
1643 (defun prolog-parse-sicstus-compilation-errors (limit)
1644 "Parse the prolog compilation buffer for errors.
1645 Argument LIMIT is a buffer position limiting searching.
1646 For use with the `compilation-parse-errors-function' variable."
1647 (setq compilation-error-list nil
)
1648 (message "Parsing SICStus error messages...")
1649 (let (filepath dir file errorline
)
1652 "{\\([a-zA-Z ]* ERROR\\|Warning\\):.* in line[s ]*\\([0-9]+\\)"
1654 (setq errorline
(string-to-number (match-string 2)))
1657 "{\\(consulting\\|compiling\\|processing\\) \\(.*\\)\\.\\.\\.}"
1659 (setq filepath
(match-string 2)))
1661 ;; ###### Does this work with SICStus under Windows
1662 ;; (i.e. backslashes and stuff?)
1663 (if (string-match "\\(.*/\\)\\([^/]*\\)$" filepath
)
1665 (setq dir
(match-string 1 filepath
))
1666 (setq file
(match-string 2 filepath
))))
1668 (setq compilation-error-list
1670 (cons (save-excursion
1673 (list (list file dir
) errorline
))
1674 compilation-error-list
)
1678 (defun prolog-consult-compile-filter (process output
)
1679 "Filter function for Prolog compilation PROCESS.
1680 Argument OUTPUT is a name of the output file."
1682 (setq prolog-consult-compile-output
1683 (concat prolog-consult-compile-output output
))
1684 ;;(message "pccf1: %s" prolog-consult-compile-output)
1685 ;; Iterate through the lines of prolog-consult-compile-output
1687 (while (and prolog-process-flag
1691 (setq outputtype
'trace
)
1692 (and (eq prolog-system
'sicstus
)
1694 "^[ \t]*[0-9]+[ \t]*[0-9]+[ \t]*Call:.*? "
1695 prolog-consult-compile-output
)))
1699 (setq outputtype
'normal
)
1700 (string-match "^.*\n" prolog-consult-compile-output
))
1702 ;;(message "outputtype: %s" outputtype)
1704 (setq output
(match-string 0 prolog-consult-compile-output
))
1705 ;; remove the text in output from prolog-consult-compile-output
1706 (setq prolog-consult-compile-output
1707 (substring prolog-consult-compile-output
(length output
)))
1708 ;;(message "pccf2: %s" prolog-consult-compile-output)
1710 ;; If temporary files were used, then we change the error
1711 ;; messages to point to the original source file.
1712 ;; FIXME: Use compilation-fake-loc instead.
1715 ;; If the prolog process was in trace mode then it requires
1717 ((and (eq prolog-system
'sicstus
)
1718 (eq outputtype
'trace
))
1719 (let ((input (concat (read-string output
) "\n")))
1720 (process-send-string process input
)
1721 (setq output
(concat output input
))))
1723 ((eq prolog-system
'sicstus
)
1724 (if (and prolog-consult-compile-real-file
1726 "\\({.*:.* in line[s ]*\\)\\([0-9]+\\)-\\([0-9]+\\)" output
))
1727 (setq output
(replace-match
1728 ;; Adds a {processing ...} line so that
1729 ;; `prolog-parse-sicstus-compilation-errors'
1730 ;; finds the real file instead of the temporary one.
1731 ;; Also fixes the line numbers.
1732 (format "Added by Emacs: {processing %s...}\n%s%d-%d"
1733 prolog-consult-compile-real-file
1734 (match-string 1 output
)
1735 (+ prolog-consult-compile-first-line
1737 (match-string 2 output
)))
1738 (+ prolog-consult-compile-first-line
1740 (match-string 3 output
))))
1744 ((eq prolog-system
'swi
)
1745 (if (and prolog-consult-compile-real-file
1746 (string-match (format
1747 "%s\\([ \t]*:[ \t]*\\)\\([0-9]+\\)"
1748 prolog-consult-compile-file
)
1750 (setq output
(replace-match
1751 ;; Real filename + text + fixed linenum
1753 prolog-consult-compile-real-file
1754 (match-string 1 output
)
1755 (+ prolog-consult-compile-first-line
1757 (match-string 2 output
))))
1763 ;; Write the output in the *prolog-compilation* buffer
1766 ;; If the prompt is visible, then the task is finished
1767 (if (string-match (prolog-prompt-regexp) prolog-consult-compile-output
)
1768 (setq prolog-process-flag nil
)))
1770 (defun prolog-consult-compile-file (compilep)
1771 "Consult/compile file of current buffer.
1772 If COMPILEP is non-nil, compile, otherwise consult."
1773 (let ((file buffer-file-name
))
1777 (prolog-consult-compile compilep file
))
1778 (prolog-consult-compile-region compilep
(point-min) (point-max)))))
1780 (defun prolog-consult-compile-buffer (compilep)
1781 "Consult/compile current buffer.
1782 If COMPILEP is non-nil, compile, otherwise consult."
1783 (prolog-consult-compile-region compilep
(point-min) (point-max)))
1785 (defun prolog-consult-compile-region (compilep beg end
)
1786 "Consult/compile region between BEG and END.
1787 If COMPILEP is non-nil, compile, otherwise consult."
1788 ;(let ((file prolog-temp-filename)
1789 (let ((file (prolog-bsts (prolog-temporary-file)))
1790 (lines (count-lines 1 beg
)))
1791 (write-region beg end file nil
'no-message
)
1792 (write-region "\n" nil file t
'no-message
)
1793 (prolog-consult-compile compilep file
1794 (if (bolp) (1+ lines
) lines
))
1795 (delete-file file
)))
1797 (defun prolog-consult-compile-predicate (compilep)
1798 "Consult/compile the predicate around current point.
1799 If COMPILEP is non-nil, compile, otherwise consult."
1800 (prolog-consult-compile-region
1801 compilep
(prolog-pred-start) (prolog-pred-end)))
1804 ;;-------------------------------------------------------------------
1806 ;;-------------------------------------------------------------------
1808 ;; Auxiliary functions
1810 (defun prolog-font-lock-object-matcher (bound)
1811 "Find SICStus objects method name for font lock.
1812 Argument BOUND is a buffer position limiting searching."
1814 (case-fold-search nil
))
1815 (while (and (not point
)
1816 (re-search-forward "\\(::[ \t\n]*{\\|&\\)[ \t]*"
1818 (while (or (re-search-forward "\\=\n[ \t]*" bound t
)
1819 (re-search-forward "\\=%.*" bound t
)
1820 (and (re-search-forward "\\=/\\*" bound t
)
1821 (re-search-forward "\\*/[ \t]*" bound t
))))
1822 (setq point
(re-search-forward
1823 (format "\\=\\(%s\\)" prolog-atom-regexp
)
1827 (defsubst prolog-face-name-p
(facename)
1828 ;; Return t if FACENAME is the name of a face. This method is
1829 ;; necessary since facep in XEmacs only returns t for the actual
1830 ;; face objects (while it's only their names that are used just
1831 ;; about anywhere else) without providing a predicate that tests
1832 ;; face names. This function (including the above commentary) is
1833 ;; borrowed from cc-mode.
1834 (memq facename
(face-list)))
1836 ;; Set everything up
1837 (defun prolog-font-lock-keywords ()
1838 "Set up font lock keywords for the current Prolog system."
1839 ;;(when window-system
1840 (require 'font-lock
)
1842 ;; Define Prolog faces
1843 (defface prolog-redo-face
1844 '((((class grayscale
)) (:italic t
))
1845 (((class color
)) (:foreground
"darkorchid"))
1847 "Prolog mode face for highlighting redo trace lines."
1848 :group
'prolog-faces
)
1849 (defface prolog-exit-face
1850 '((((class grayscale
)) (:underline t
))
1851 (((class color
) (background dark
)) (:foreground
"green"))
1852 (((class color
) (background light
)) (:foreground
"ForestGreen"))
1854 "Prolog mode face for highlighting exit trace lines."
1855 :group
'prolog-faces
)
1856 (defface prolog-exception-face
1857 '((((class grayscale
)) (:bold t
:italic t
:underline t
))
1858 (((class color
)) (:bold t
:foreground
"black" :background
"Khaki"))
1859 (t (:bold t
:italic t
:underline t
)))
1860 "Prolog mode face for highlighting exception trace lines."
1861 :group
'prolog-faces
)
1862 (defface prolog-warning-face
1863 '((((class grayscale
)) (:underline t
))
1864 (((class color
) (background dark
)) (:foreground
"blue"))
1865 (((class color
) (background light
)) (:foreground
"MidnightBlue"))
1867 "Face name to use for compiler warnings."
1868 :group
'prolog-faces
)
1869 (defface prolog-builtin-face
1870 '((((class color
) (background light
)) (:foreground
"Purple"))
1871 (((class color
) (background dark
)) (:foreground
"Cyan"))
1872 (((class grayscale
) (background light
))
1873 :foreground
"LightGray" :bold t
)
1874 (((class grayscale
) (background dark
)) (:foreground
"DimGray" :bold t
))
1876 "Face name to use for compiler warnings."
1877 :group
'prolog-faces
)
1878 (defvar prolog-warning-face
1879 (if (prolog-face-name-p 'font-lock-warning-face
)
1880 'font-lock-warning-face
1881 'prolog-warning-face
)
1882 "Face name to use for built in predicates.")
1883 (defvar prolog-builtin-face
1884 (if (prolog-face-name-p 'font-lock-builtin-face
)
1885 'font-lock-builtin-face
1886 'prolog-builtin-face
)
1887 "Face name to use for built in predicates.")
1888 (defvar prolog-redo-face
'prolog-redo-face
1889 "Face name to use for redo trace lines.")
1890 (defvar prolog-exit-face
'prolog-exit-face
1891 "Face name to use for exit trace lines.")
1892 (defvar prolog-exception-face
'prolog-exception-face
1893 "Face name to use for exception trace lines.")
1895 ;; Font Lock Patterns
1897 ;; "Native" Prolog patterns
1899 (list (format "^\\(%s\\)\\((\\|[ \t]*:-\\)" prolog-atom-regexp
)
1900 1 font-lock-function-name-face
))
1901 ;(list (format "^%s" prolog-atom-regexp)
1902 ; 0 font-lock-function-name-face))
1904 (list (format "\\.[ \t]*\\(%s\\)" prolog-atom-regexp
)
1905 1 font-lock-function-name-face
) )
1907 '("\\<\\([_A-Z][a-zA-Z0-9_]*\\)"
1908 1 font-lock-variable-name-face
))
1910 (list (if (eq prolog-system
'mercury
)
1911 "[][}{;|]\\|\\\\[+=]\\|<?=>?"
1912 "[][}{!;|]\\|\\*->")
1913 0 'font-lock-keyword-face
))
1914 (important-elements-1
1915 '("[^-*]\\(->\\)" 1 font-lock-keyword-face
))
1916 (predspecs ; module:predicate/cardinality
1917 (list (format "\\<\\(%s:\\|\\)%s/[0-9]+"
1918 prolog-atom-regexp prolog-atom-regexp
)
1919 0 font-lock-function-name-face
'prepend
))
1920 (keywords ; directives (queries)
1922 (if (eq prolog-system
'mercury
)
1925 (regexp-opt prolog-keywords-i
)
1928 prolog-determinism-specificators-i
)
1932 (regexp-opt prolog-keywords-i
)
1934 1 prolog-builtin-face
))
1935 ;; SICStus specific patterns
1936 (sicstus-object-methods
1937 (if (eq prolog-system
'sicstus
)
1938 '(prolog-font-lock-object-matcher
1939 1 font-lock-function-name-face
)))
1940 ;; Mercury specific patterns
1942 (if (eq prolog-system
'mercury
)
1944 (regexp-opt prolog-types-i
'words
)
1945 0 'font-lock-type-face
)))
1947 (if (eq prolog-system
'mercury
)
1949 (regexp-opt prolog-mode-specificators-i
'words
)
1950 0 'font-lock-constant-face
)))
1952 (if (eq prolog-system
'mercury
)
1954 (regexp-opt prolog-directives-i
'words
)
1955 0 'prolog-warning-face
)))
1956 ;; Inferior mode specific patterns
1958 ;; FIXME: Should be handled by comint already.
1959 (list (prolog-prompt-regexp) 0 'font-lock-keyword-face
))
1961 ;; FIXME: Add to compilation-error-regexp-alist instead.
1963 ((eq prolog-system
'sicstus
)
1964 '("[ \t]*[0-9]+[ \t]+[0-9]+[ \t]*\\(Exit\\):"
1965 1 prolog-exit-face
))
1966 ((eq prolog-system
'swi
)
1967 '("[ \t]*\\(Exit\\):[ \t]*([ \t0-9]*)" 1 prolog-exit-face
))
1970 ;; FIXME: Add to compilation-error-regexp-alist instead.
1972 ((eq prolog-system
'sicstus
)
1973 '("[ \t]*[0-9]+[ \t]+[0-9]+[ \t]*\\(Fail\\):"
1974 1 prolog-warning-face
))
1975 ((eq prolog-system
'swi
)
1976 '("[ \t]*\\(Fail\\):[ \t]*([ \t0-9]*)" 1 prolog-warning-face
))
1979 ;; FIXME: Add to compilation-error-regexp-alist instead.
1981 ((eq prolog-system
'sicstus
)
1982 '("[ \t]*[0-9]+[ \t]+[0-9]+[ \t]*\\(Redo\\):"
1983 1 prolog-redo-face
))
1984 ((eq prolog-system
'swi
)
1985 '("[ \t]*\\(Redo\\):[ \t]*([ \t0-9]*)" 1 prolog-redo-face
))
1988 ;; FIXME: Add to compilation-error-regexp-alist instead.
1990 ((eq prolog-system
'sicstus
)
1991 '("[ \t]*[0-9]+[ \t]+[0-9]+[ \t]*\\(Call\\):"
1992 1 font-lock-function-name-face
))
1993 ((eq prolog-system
'swi
)
1994 '("[ \t]*\\(Call\\):[ \t]*([ \t0-9]*)"
1995 1 font-lock-function-name-face
))
1998 ;; FIXME: Add to compilation-error-regexp-alist instead.
2000 ((eq prolog-system
'sicstus
)
2001 '("[ \t]*[0-9]+[ \t]+[0-9]+[ \t]*\\(Exception\\):"
2002 1 prolog-exception-face
))
2003 ((eq prolog-system
'swi
)
2004 '("[ \t]*\\(Exception\\):[ \t]*([ \t0-9]*)"
2005 1 prolog-exception-face
))
2007 (error-message-identifier
2008 ;; FIXME: Add to compilation-error-regexp-alist instead.
2010 ((eq prolog-system
'sicstus
)
2011 '("{\\([A-Z]* ?ERROR:\\)" 1 prolog-exception-face prepend
))
2012 ((eq prolog-system
'swi
)
2013 '("^[[]\\(WARNING:\\)" 1 prolog-builtin-face prepend
))
2015 (error-whole-messages
2016 ;; FIXME: Add to compilation-error-regexp-alist instead.
2018 ((eq prolog-system
'sicstus
)
2019 '("{\\([A-Z]* ?ERROR:.*\\)}[ \t]*$"
2020 1 font-lock-comment-face append
))
2021 ((eq prolog-system
'swi
)
2022 '("^[[]WARNING:[^]]*[]]$" 0 font-lock-comment-face append
))
2024 (error-warning-messages
2025 ;; FIXME: Add to compilation-error-regexp-alist instead.
2026 ;; Mostly errors that SICStus asks the user about how to solve,
2027 ;; such as "NAME CLASH:" for example.
2029 ((eq prolog-system
'sicstus
)
2030 '("^[A-Z ]*[A-Z]+:" 0 prolog-warning-face
))
2033 ;; FIXME: Add to compilation-error-regexp-alist instead.
2035 ((eq prolog-system
'sicstus
)
2036 '("\\({ ?\\(Warning\\|WARNING\\) ?:.*}\\)[ \t]*$"
2037 2 prolog-warning-face prepend
))
2040 ;; Make font lock list
2044 ((eq major-mode
'prolog-mode
)
2050 important-elements-1
2053 sicstus-object-methods
2057 ((eq major-mode
'prolog-inferior-mode
)
2060 error-message-identifier
2061 error-whole-messages
2062 error-warning-messages
2070 ((eq major-mode
'compilation-mode
)
2072 error-message-identifier
2073 error-whole-messages
2074 error-warning-messages
2081 (defun prolog-find-unmatched-paren ()
2082 "Return the column of the last unmatched left parenthesis."
2084 (goto-char (or (car (nth 9 (syntax-ppss))) (point-min)))
2088 (defun prolog-paren-balance ()
2089 "Return the parenthesis balance of the current line.
2090 A return value of N means N more left parentheses than right ones."
2092 (car (parse-partial-sexp (line-beginning-position)
2093 (line-end-position)))))
2095 (defun prolog-electric--if-then-else ()
2096 "Insert spaces after the opening parenthesis, \"then\" (->) and \"else\" (;) branches.
2097 Spaces are inserted if all preceding objects on the line are
2098 whitespace characters, parentheses, or then/else branches."
2099 (when prolog-electric-if-then-else-flag
2101 (let ((regexp (concat "(\\|" prolog-left-indent-regexp
))
2105 (skip-chars-forward " \t")
2106 ;; Treat "( If -> " lines specially.
2107 ;;(setq incr (if (looking-at "(.*->")
2109 ;; prolog-paren-indent))
2111 ;; work on all subsequent "->", "(", ";"
2112 (and (looking-at regexp
)
2113 (= pos
(match-end 0))
2114 (indent-according-to-mode))
2115 (while (looking-at regexp
)
2116 (goto-char (match-end 0))
2117 (setq level
(+ (prolog-find-unmatched-paren) prolog-paren-indent
))
2119 ;; Remove old white space
2120 (let ((start (point)))
2121 (skip-chars-forward " \t")
2122 (delete-region start
(point)))
2124 (skip-chars-forward " \t"))
2126 (when (save-excursion
2128 (looking-at "\\s ;\\|\\s (\\|->")) ; (looking-at "\\s \\((\\|;\\)"))
2129 (skip-chars-forward " \t"))
2132 ;;;; Comment filling
2134 (defun prolog-comment-limits ()
2135 "Return the current comment limits plus the comment type (block or line).
2136 The comment limits are the range of a block comment or the range that
2137 contains all adjacent line comments (i.e. all comments that starts in
2138 the same column with no empty lines or non-whitespace characters
2140 (let ((here (point))
2141 lit-limits-b lit-limits-e lit-type beg end
2144 ;; Widen to catch comment limits correctly.
2146 (setq end
(line-end-position)
2147 beg
(line-beginning-position))
2150 (setq lit-type
(if (search-forward-regexp "%" end t
) 'line
'block
))
2151 ; (setq lit-type 'line)
2152 ;(if (search-forward-regexp "^[ \t]*%" end t)
2153 ; (setq lit-type 'line)
2154 ; (if (not (search-forward-regexp "%" end t))
2155 ; (setq lit-type 'block)
2156 ; (if (not (= (forward-line 1) 0))
2157 ; (setq lit-type 'block)
2159 ; ret (prolog-comment-limits)))
2161 (if (eq lit-type
'block
)
2164 (when (looking-at "/\\*") (forward-char 2))
2165 (when (and (looking-at "\\*") (> (point) (point-min))
2166 (forward-char -
1) (looking-at "/"))
2168 (when (save-excursion (search-backward "/*" nil t
))
2169 (list (save-excursion (search-backward "/*") (point))
2170 (or (search-forward "*/" nil t
) (point-max)) lit-type
)))
2172 (setq lit-limits-b
(- (point) 1)
2175 (if (progn (goto-char lit-limits-b
)
2177 (let ((col (current-column)) done
)
2180 ;; Always at the beginning of the comment
2183 (while (and (zerop (setq done
(forward-line -
1)))
2184 (search-forward-regexp "^[ \t]*%"
2185 (line-end-position) t
)
2186 (= (+ 1 col
) (current-column)))
2187 (setq beg
(- (point) 1)))
2190 ;; We may have a line with code above...
2191 (when (and (zerop (setq done
(forward-line -
1)))
2192 (search-forward "%" (line-end-position) t
)
2193 (= (+ 1 col
) (current-column)))
2194 (setq beg
(- (point) 1)))
2198 (goto-char lit-limits-b
)
2200 (while (and (zerop (forward-line 1))
2201 (search-forward-regexp "^[ \t]*%"
2202 (line-end-position) t
)
2203 (= (+ 1 col
) (current-column)))
2204 (setq end
(line-end-position)))
2205 (list beg end lit-type
))
2206 (list lit-limits-b lit-limits-e lit-type
)
2208 (error (list lit-limits-b lit-limits-e lit-type
))))
2211 (defun prolog-guess-fill-prefix ()
2212 ;; fill 'txt entities?
2213 (when (save-excursion
2215 (nth 4 (syntax-ppss)))
2216 (let* ((bounds (prolog-comment-limits))
2218 (type (nth 2 bounds
))
2225 (if (and (eq type
'line
)
2227 (save-excursion (not (search-forward-regexp "^[ \t]*%"
2231 (search-forward-regexp "%+[ \t]*" end t
)
2232 (prolog-replace-in-string (buffer-substring beg
(point))
2235 (if (search-forward-regexp "^[ \t]*\\(%+\\|\\*+\\|/\\*+\\)[ \t]*"
2237 (prolog-replace-in-string (buffer-substring beg
(point)) "/" " ")
2239 (when (search-forward-regexp "^[ \t]+" end t
)
2240 (buffer-substring beg
(point)))))))))
2242 (defun prolog-fill-paragraph ()
2243 "Fill paragraph comment at or after point."
2245 (let* ((bounds (prolog-comment-limits))
2246 (type (nth 2 bounds
)))
2248 (let ((fill-prefix (prolog-guess-fill-prefix)))
2249 (fill-paragraph nil
))
2252 ;; exclude surrounding lines that delimit a multiline comment
2253 ;; and don't contain alphabetic characters, like "/*******",
2256 (backward-paragraph)
2257 (unless (bobp) (forward-line))
2258 (if (string-match "^/\\*[^a-zA-Z]*$" (thing-at-point 'line
))
2259 (narrow-to-region (point-at-eol) (point-max))))
2263 (if (string-match "^[^a-zA-Z]*\\*/$" (thing-at-point 'line
))
2264 (narrow-to-region (point-min) (point-at-bol))))
2265 (let ((fill-prefix (prolog-guess-fill-prefix)))
2266 (fill-paragraph nil
))))
2269 (defun prolog-do-auto-fill ()
2270 "Carry out Auto Fill for Prolog mode.
2271 In effect it sets the `fill-prefix' when inside comments and then calls
2273 (let ((fill-prefix (prolog-guess-fill-prefix)))
2277 (defalias 'prolog-replace-in-string
2278 (if (fboundp 'replace-in-string
)
2280 (lambda (str regexp newtext
&optional literal
)
2281 (replace-regexp-in-string regexp newtext str nil literal
))))
2283 ;;-------------------------------------------------------------------
2285 ;;-------------------------------------------------------------------
2287 (defvar prolog-help-function
2289 (eclipse prolog-help-online
)
2290 ;; (sicstus prolog-help-info)
2291 (sicstus prolog-find-documentation
)
2292 (swi prolog-help-online
)
2293 (t prolog-help-online
))
2294 "Alist for the name of the function for finding help on a predicate.")
2296 (defun prolog-help-on-predicate ()
2297 "Invoke online help on the atom under cursor."
2301 ;; Redirect help for SICStus to `prolog-find-documentation'.
2302 ((eq prolog-help-function-i
'prolog-find-documentation
)
2303 (prolog-find-documentation))
2305 ;; Otherwise, ask for the predicate name and then call the function
2306 ;; in prolog-help-function-i
2308 (let* ((word (prolog-atom-under-point))
2309 (predicate (read-string
2310 (format "Help on predicate%s: "
2312 (concat " (default " word
")")
2317 (if prolog-help-function-i
2318 (funcall prolog-help-function-i predicate
)
2319 (error "Sorry, no help method defined for this Prolog system."))))
2323 (autoload 'Info-goto-node
"info" nil t
)
2324 (declare-function Info-follow-nearest-node
"info" (&optional FORK
))
2326 (defun prolog-help-info (predicate)
2327 (let ((buffer (current-buffer))
2329 (str (concat "^\\* " (regexp-quote predicate
) " */")))
2331 (Info-goto-node prolog-info-predicate-index
)
2332 (if (not (re-search-forward str nil t
))
2333 (error "Help on predicate `%s' not found." predicate
))
2336 (if (re-search-forward str nil t
)
2337 ;; Multiple matches, ask user
2341 (while (re-search-forward str nil t
)
2342 (setq max
(1+ max
)))
2345 (re-search-backward "[^ /]" nil t
)
2347 (setq n
(read-string ;; was read-input, which is obsolete
2348 (format "Several matches, choose (1-%d): " max
) "1"))
2349 (forward-line (- (string-to-number n
) 1)))
2351 (re-search-backward "[^ /]" nil t
))
2353 ;; (Info-follow-nearest-node (point))
2354 (prolog-Info-follow-nearest-node)
2355 (re-search-forward (concat "^`" (regexp-quote predicate
)) nil t
)
2358 (pop-to-buffer buffer
)))
2360 (defun prolog-Info-follow-nearest-node ()
2361 (if (featurep 'xemacs
)
2362 (Info-follow-nearest-node (point))
2363 (Info-follow-nearest-node)))
2365 (defun prolog-help-online (predicate)
2366 (prolog-ensure-process)
2367 (process-send-string "prolog" (concat "help(" predicate
").\n"))
2368 (display-buffer "*prolog*"))
2370 (defun prolog-help-apropos (string)
2371 "Find Prolog apropos on given STRING.
2372 This function is only available when `prolog-system' is set to `swi'."
2373 (interactive "sApropos: ")
2375 ((eq prolog-system
'swi
)
2376 (prolog-ensure-process)
2377 (process-send-string "prolog" (concat "apropos(" string
").\n"))
2378 (display-buffer "*prolog*"))
2380 (error "Sorry, no Prolog apropos available for this Prolog system."))))
2382 (defun prolog-atom-under-point ()
2383 "Return the atom under or left to the point."
2385 (let ((nonatom_chars "[](){},. \t\n")
2387 (skip-chars-forward (concat "^" nonatom_chars
))
2388 (skip-chars-backward nonatom_chars
)
2389 (skip-chars-backward (concat "^" nonatom_chars
))
2390 (setq start
(point))
2391 (skip-chars-forward (concat "^" nonatom_chars
))
2392 (buffer-substring-no-properties start
(point))
2396 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2397 ;; Help function with completion
2398 ;; Stolen from Per Mildner's SICStus debugger mode and modified
2400 (defun prolog-find-documentation ()
2401 "Go to the Info node for a predicate in the SICStus Info manual."
2403 (let ((pred (prolog-read-predicate)))
2404 (prolog-goto-predicate-info pred
)))
2406 (defvar prolog-info-alist nil
2407 "Alist with all builtin predicates.
2408 Only for internal use by `prolog-find-documentation'")
2410 ;; Very similar to prolog-help-info except that that function cannot
2411 ;; cope with arity and that it asks the user if there are several
2412 ;; functors with different arity. This function also uses
2413 ;; prolog-info-alist for finding the info node, rather than parsing
2414 ;; the predicate index.
2415 (defun prolog-goto-predicate-info (predicate)
2416 "Go to the info page for PREDICATE, which is a PredSpec."
2418 (string-match "\\(.*\\)/\\([0-9]+\\).*$" predicate
)
2419 (let ((buffer (current-buffer))
2420 (name (match-string 1 predicate
))
2421 (arity (string-to-number (match-string 2 predicate
)))
2423 ;(str (regexp-quote predicate))
2428 prolog-info-predicate-index
) ;; We must be in the SICStus pages
2429 (Info-goto-node (car (cdr (assoc predicate prolog-info-alist
))))
2431 (prolog-find-term (regexp-quote name
) arity
"^`")
2434 (pop-to-buffer buffer
))
2437 (defun prolog-read-predicate ()
2438 "Read a PredSpec from the user.
2439 Returned value is a string \"FUNCTOR/ARITY\".
2440 Interaction supports completion."
2441 (let ((default (prolog-atom-under-point)))
2442 ;; If the predicate index is not yet built, do it now
2443 (if (not prolog-info-alist
)
2444 (prolog-build-info-alist))
2445 ;; Test if the default string could be the base for completion.
2446 ;; Discard it if not.
2447 (if (eq (try-completion default prolog-info-alist
) nil
)
2449 ;; Read the PredSpec from the user
2451 (if (zerop (length default
))
2452 "Help on predicate: "
2453 (concat "Help on predicate (default " default
"): "))
2454 prolog-info-alist nil t nil nil default
)))
2456 (defun prolog-build-info-alist (&optional verbose
)
2457 "Build an alist of all builtins and library predicates.
2458 Each element is of the form (\"NAME/ARITY\" . (INFO-NODE1 INFO-NODE2 ...)).
2459 Typically there is just one Info node associated with each name
2460 If an optional argument VERBOSE is non-nil, print messages at the beginning
2461 and end of list building."
2463 (message "Building info alist..."))
2464 (setq prolog-info-alist
2466 (last-entry (cons "" ())))
2468 (save-window-excursion
2469 ;; select any window but the minibuffer (as we cannot switch
2470 ;; buffers in minibuffer window.
2471 ;; I am not sure this is the right/best way
2472 (if (active-minibuffer-window) ; nil if none active
2473 (select-window (next-window)))
2474 ;; Do this after going away from minibuffer window
2475 (save-window-excursion
2477 (Info-goto-node prolog-info-predicate-index
)
2478 (goto-char (point-min))
2479 (while (re-search-forward
2480 "^\\* \\(.+\\)/\\([0-9]+\\)\\([^\n:*]*\\):" nil t
)
2481 (let* ((name (match-string 1))
2482 (arity (string-to-number (match-string 2)))
2483 (comment (match-string 3))
2484 (fa (format "%s/%d%s" name arity comment
))
2487 ;; Extract the info node name
2488 (setq info-node
(progn
2489 (re-search-forward ":[ \t]*\\([^:]+\\).$")
2492 ;; ###### Easier? (from Milan version 0.1.28)
2493 ;; (setq info-node (Info-extract-menu-node-name))
2494 (if (equal fa
(car last-entry
))
2495 (setcdr last-entry
(cons info-node
(cdr last-entry
)))
2496 (setq last-entry
(cons fa
(list info-node
))
2497 l
(cons last-entry l
)))))
2501 (message "Building info alist... done.")))
2504 ;;-------------------------------------------------------------------
2505 ;; Miscellaneous functions
2506 ;;-------------------------------------------------------------------
2508 ;; For Windows. Change backslash to slash. SICStus handles either
2509 ;; path separator but backslash must be doubled, therefore use slash.
2510 (defun prolog-bsts (string)
2511 "Change backslashes to slashes in STRING."
2512 (let ((str1 (copy-sequence string
))
2513 (len (length string
))
2516 (if (char-equal (aref str1 i
) ?
\\)
2521 ;;(defun prolog-temporary-file ()
2522 ;; "Make temporary file name for compilation."
2526 ;; (getenv "TMPDIR")
2529 ;; (getenv "SYSTEMP")
2532 ;;(setq prolog-temp-filename (prolog-bsts (prolog-temporary-file)))
2534 (defun prolog-temporary-file ()
2535 "Make temporary file name for compilation."
2536 (if prolog-temporary-file-name
2537 ;; We already have a file, erase content and continue
2539 (write-region "" nil prolog-temporary-file-name nil
'silent
)
2540 prolog-temporary-file-name
)
2541 ;; Actually create the file and set `prolog-temporary-file-name'
2543 (setq prolog-temporary-file-name
2544 (make-temp-file "prolcomp" nil
".pl"))))
2546 (defun prolog-goto-prolog-process-buffer ()
2547 "Switch to the prolog process buffer and go to its end."
2548 (switch-to-buffer-other-window "*prolog*")
2549 (goto-char (point-max))
2552 (defun prolog-enable-sicstus-sd ()
2553 "Enable the source level debugging facilities of SICStus 3.7 and later."
2555 (require 'pltrace
) ; Load the SICStus debugger code
2556 ;; Turn on the source level debugging by default
2557 (add-hook 'prolog-inferior-mode-hook
'pltrace-on
)
2558 (if (not prolog-use-sicstus-sd
)
2560 ;; If there is a *prolog* buffer, then call pltrace-on
2561 (if (get-buffer "*prolog*")
2562 ;; Avoid compilation warnings by using eval
2563 (eval '(pltrace-on)))
2564 (setq prolog-use-sicstus-sd t
)
2567 (defun prolog-disable-sicstus-sd ()
2568 "Disable the source level debugging facilities of SICStus 3.7 and later."
2570 (setq prolog-use-sicstus-sd nil
)
2572 (remove-hook 'prolog-inferior-mode-hook
'pltrace-on
)
2573 ;; If there is a *prolog* buffer, then call pltrace-off
2574 (if (get-buffer "*prolog*")
2575 ;; Avoid compile warnings by using eval
2576 (eval '(pltrace-off))))
2578 (defun prolog-toggle-sicstus-sd ()
2579 ;; FIXME: Use define-minor-mode.
2580 "Toggle the source level debugging facilities of SICStus 3.7 and later."
2582 (if prolog-use-sicstus-sd
2583 (prolog-disable-sicstus-sd)
2584 (prolog-enable-sicstus-sd)))
2586 (defun prolog-debug-on (&optional arg
)
2588 When called with prefix argument ARG, disable debugging instead."
2592 (prolog-process-insert-string (get-process "prolog")
2593 prolog-debug-on-string
)
2594 (process-send-string "prolog" prolog-debug-on-string
)))
2596 (defun prolog-debug-off ()
2597 "Disable debugging."
2599 (prolog-process-insert-string (get-process "prolog")
2600 prolog-debug-off-string
)
2601 (process-send-string "prolog" prolog-debug-off-string
))
2603 (defun prolog-trace-on (&optional arg
)
2605 When called with prefix argument ARG, disable tracing instead."
2609 (prolog-process-insert-string (get-process "prolog")
2610 prolog-trace-on-string
)
2611 (process-send-string "prolog" prolog-trace-on-string
)))
2613 (defun prolog-trace-off ()
2616 (prolog-process-insert-string (get-process "prolog")
2617 prolog-trace-off-string
)
2618 (process-send-string "prolog" prolog-trace-off-string
))
2620 (defun prolog-zip-on (&optional arg
)
2621 "Enable zipping (for SICStus 3.7 and later).
2622 When called with prefix argument ARG, disable zipping instead."
2624 (if (not (and (eq prolog-system
'sicstus
)
2625 (prolog-atleast-version '(3 .
7))))
2626 (error "Only works for SICStus 3.7 and later"))
2629 (prolog-process-insert-string (get-process "prolog")
2630 prolog-zip-on-string
)
2631 (process-send-string "prolog" prolog-zip-on-string
)))
2633 (defun prolog-zip-off ()
2634 "Disable zipping (for SICStus 3.7 and later)."
2636 (prolog-process-insert-string (get-process "prolog")
2637 prolog-zip-off-string
)
2638 (process-send-string "prolog" prolog-zip-off-string
))
2640 ;; (defun prolog-create-predicate-index ()
2641 ;; "Create an index for all predicates in the buffer."
2642 ;; (let ((predlist '())
2647 ;; (goto-char (point-min))
2648 ;; ;; Replace with prolog-clause-start!
2649 ;; (while (re-search-forward "^.+:-" nil t)
2650 ;; (setq pos (match-beginning 0))
2651 ;; (setq clauseinfo (prolog-clause-info))
2652 ;; (setq object (prolog-in-object))
2653 ;; (setq predlist (append
2656 ;; (if (and (eq prolog-system 'sicstus)
2657 ;; (prolog-in-object))
2658 ;; (format "%s::%s/%d"
2660 ;; (nth 0 clauseinfo)
2661 ;; (nth 1 clauseinfo))
2663 ;; (nth 0 clauseinfo)
2664 ;; (nth 1 clauseinfo)))
2667 ;; (prolog-end-of-predicate))
2670 (defun prolog-get-predspec ()
2672 (let ((state (prolog-clause-info))
2673 (object (prolog-in-object)))
2674 (if (or (equal (nth 0 state
) "")
2675 (nth 4 (syntax-ppss)))
2677 (if (and (eq prolog-system
'sicstus
)
2688 ;; For backward compatibility. Stolen from custom.el.
2689 (or (fboundp 'match-string
)
2690 ;; Introduced in Emacs 19.29.
2691 (defun match-string (num &optional string
)
2692 "Return string of text matched by last search.
2693 NUM specifies which parenthesized expression in the last regexp.
2694 Value is nil if NUMth pair didn't match, or there were less than NUM pairs.
2695 Zero means the entire text matched by the whole regexp or whole string.
2696 STRING should be given if the last search was by `string-match' on STRING."
2697 (if (match-beginning num
)
2699 (substring string
(match-beginning num
) (match-end num
))
2700 (buffer-substring (match-beginning num
) (match-end num
))))))
2702 (defun prolog-pred-start ()
2703 "Return the starting point of the first clause of the current predicate."
2706 (goto-char (prolog-clause-start))
2707 ;; Find first clause, unless it was a directive
2708 (if (and (not (looking-at "[:?]-"))
2709 (not (looking-at "[ \t]*[%/]")) ; Comment
2712 (let* ((pinfo (prolog-clause-info))
2713 (predname (nth 0 pinfo
))
2714 (arity (nth 1 pinfo
))
2716 (while (and (re-search-backward
2717 (format "^%s\\([(\\.]\\| *%s\\)"
2718 predname prolog-head-delimiter
) nil t
)
2719 (= arity
(nth 1 (prolog-clause-info)))
2722 (if (eq prolog-system
'mercury
)
2723 ;; Skip to the beginning of declarations of the predicate
2725 (goto-char (prolog-beginning-of-clause))
2726 (while (and (not (eq (point) op
))
2728 (format ":-[ \t]*\\(pred\\|mode\\)[ \t]+%s"
2731 (goto-char (prolog-beginning-of-clause)))))
2735 (defun prolog-pred-end ()
2736 "Return the position at the end of the last clause of the current predicate."
2739 (goto-char (prolog-clause-end)) ; If we are before the first predicate.
2740 (goto-char (prolog-clause-start))
2741 (let* ((pinfo (prolog-clause-info))
2742 (predname (nth 0 pinfo
))
2743 (arity (nth 1 pinfo
))
2747 (if (looking-at "[:?]-")
2748 ;; This was a directive
2750 (if (and (eq prolog-system
'mercury
)
2752 (format ":-[ \t]*\\(pred\\|mode\\)[ \t]+\\(%s+\\)"
2753 prolog-atom-regexp
)))
2754 ;; Skip predicate declarations
2756 (setq predname
(buffer-substring-no-properties
2757 (match-beginning 2) (match-end 2)))
2758 (while (re-search-forward
2760 "\n*\\(:-[ \t]*\\(pred\\|mode\\)[ \t]+\\)?%s[( \t]"
2763 (goto-char (prolog-clause-end))
2765 ;; It was not a directive, find the last clause
2768 (format "^%s\\([(\\.]\\| *%s\\)"
2769 predname prolog-head-delimiter
) nil t
)
2770 (= arity
(nth 1 (prolog-clause-info))))
2772 (setq op
(prolog-clause-end))
2774 ;; End of clause not found.
2776 ;; Continue while loop
2780 (defun prolog-clause-start (&optional not-allow-methods
)
2781 "Return the position at the start of the head of the current clause.
2782 If NOTALLOWMETHODS is non-nil then do not match on methods in
2783 objects (relevant only if `prolog-system' is set to `sicstus')."
2786 (retval (point-min)))
2790 (if (and (not not-allow-methods
)
2791 (eq prolog-system
'sicstus
)
2795 ;; Search for a head or a fact
2797 ;; If in object, then find method start.
2798 ;; "^[ \t]+[a-z$].*\\(:-\\|&\\|:: {\\|,\\)"
2799 "^[ \t]+[a-z$].*\\(:-\\|&\\|:: {\\)" ; The comma causes
2800 ; problems since we cannot assume
2801 ; that the line starts at column 0,
2802 ; thus we don't know if the line
2803 ; is a head or a subgoal
2805 (if (>= (prolog-paren-balance) 0) ; To no match on " a) :-"
2806 ;; Start of method found
2808 (setq retval
(point))
2809 (setq notdone nil
)))
2815 ;; Search for a text at beginning of a line
2817 ;; (re-search-backward "^[a-z$']" nil t))
2818 (let ((case-fold-search nil
))
2819 (re-search-backward "^\\([[:lower:]$']\\|[:?]-\\)"
2821 (let ((bal (prolog-paren-balance)))
2824 ;; Start of clause found
2826 (setq retval
(point))
2827 (setq notdone nil
)))
2830 (format ".*\\(\\.\\|%s\\|!,\\)[ \t]*\\(%%.*\\|\\)$"
2831 prolog-head-delimiter
)))
2832 ;; Start of clause found if the line ends with a '.' or
2833 ;; a prolog-head-delimiter
2835 (setq retval
(point))
2838 (t nil
) ; Do nothing
2843 (defun prolog-clause-end (&optional not-allow-methods
)
2844 "Return the position at the end of the current clause.
2845 If NOTALLOWMETHODS is non-nil then do not match on methods in
2846 objects (relevant only if `prolog-system' is set to `sicstus')."
2848 (beginning-of-line) ; Necessary since we use "^...." for the search.
2849 (if (re-search-forward
2850 (if (and (not not-allow-methods
)
2851 (eq prolog-system
'sicstus
)
2854 "^\\(%s\\|%s\\|[^\n'\"%%]\\)*&[ \t]*\\(\\|%%.*\\)$\\|[ \t]*}"
2855 prolog-quoted-atom-regexp prolog-string-regexp
)
2857 "^\\(%s\\|%s\\|[^\n'\"%%]\\)*\\.[ \t]*\\(\\|%%.*\\)$"
2858 prolog-quoted-atom-regexp prolog-string-regexp
))
2860 (if (and (nth 8 (syntax-ppss))
2864 (prolog-clause-end))
2868 (defun prolog-clause-info ()
2869 "Return a (name arity) list for the current clause."
2871 (goto-char (prolog-clause-start))
2874 (if (looking-at prolog-atom-char-regexp
)
2876 (skip-chars-forward "^ (\\.")
2877 (buffer-substring op
(point)))
2880 ;; Retrieve the arity.
2881 (if (looking-at prolog-left-paren
)
2882 (let ((endp (save-excursion
2883 (forward-list) (point))))
2885 (forward-char 1) ; Skip the opening paren.
2887 (skip-chars-forward "^[({,'\"")
2889 (if (looking-at ",")
2891 (setq arity
(1+ arity
))
2892 (forward-char 1) ; Skip the comma.
2894 ;; We found a string, list or something else we want
2898 (list predname arity
))))
2900 (defun prolog-in-object ()
2901 "Return object name if the point is inside a SICStus object definition."
2902 ;; Return object name if the last line that starts with a character
2903 ;; that is neither white space nor a comment start
2907 (looking-at "\\([^\n ]+\\)[ \t]*::[ \t]*{"))
2908 ;; We were in the head of the object
2910 ;; We were not in the head
2911 (if (and (re-search-backward "^[a-z$'}]" nil t
)
2912 (looking-at "\\([^\n ]+\\)[ \t]*::[ \t]*{"))
2916 (defun prolog-beginning-of-clause ()
2917 "Move to the beginning of current clause.
2918 If already at the beginning of clause, move to previous clause."
2920 (let ((point (point))
2921 (new-point (prolog-clause-start)))
2922 (if (and (>= new-point point
)
2925 (goto-char (1- point
))
2926 (goto-char (prolog-clause-start)))
2927 (goto-char new-point
)
2928 (skip-chars-forward " \t"))))
2930 ;; (defun prolog-previous-clause ()
2931 ;; "Move to the beginning of the previous clause."
2933 ;; (forward-char -1)
2934 ;; (prolog-beginning-of-clause))
2936 (defun prolog-end-of-clause ()
2937 "Move to the end of clause.
2938 If already at the end of clause, move to next clause."
2940 (let ((point (point))
2941 (new-point (prolog-clause-end)))
2942 (if (and (<= new-point point
)
2943 (not (eq new-point
(point-max))))
2945 (goto-char (1+ point
))
2946 (goto-char (prolog-clause-end)))
2947 (goto-char new-point
))))
2949 ;; (defun prolog-next-clause ()
2950 ;; "Move to the beginning of the next clause."
2952 ;; (prolog-end-of-clause)
2954 ;; (prolog-end-of-clause)
2955 ;; (prolog-beginning-of-clause))
2957 (defun prolog-beginning-of-predicate ()
2958 "Go to the nearest beginning of predicate before current point.
2959 Return the final point or nil if no such a beginning was found."
2960 ;; FIXME: Hook into beginning-of-defun.
2963 (pos (prolog-pred-start)))
2970 (setq pos
(prolog-pred-start))
2978 (defun prolog-end-of-predicate ()
2979 "Go to the end of the current predicate."
2980 ;; FIXME: Hook into end-of-defun.
2983 (goto-char (prolog-pred-end))
2987 (prolog-end-of-predicate)))))
2989 (defun prolog-insert-predspec ()
2990 "Insert the predspec for the current predicate."
2992 (let* ((pinfo (prolog-clause-info))
2993 (predname (nth 0 pinfo
))
2994 (arity (nth 1 pinfo
)))
2995 (insert (format "%s/%d" predname arity
))))
2997 (defun prolog-view-predspec ()
2998 "Insert the predspec for the current predicate."
3000 (let* ((pinfo (prolog-clause-info))
3001 (predname (nth 0 pinfo
))
3002 (arity (nth 1 pinfo
)))
3003 (message "%s/%d" predname arity
)))
3005 (defun prolog-insert-predicate-template ()
3006 "Insert the template for the current clause."
3010 (pinfo (prolog-clause-info))
3011 (predname (nth 0 pinfo
))
3012 (arity (nth 1 pinfo
)))
3017 (when prolog-electric-dot-full-predicate-template
3027 (defun prolog-insert-next-clause ()
3028 "Insert newline and the name of the current clause."
3031 (prolog-insert-predicate-template))
3033 (defun prolog-insert-module-modeline ()
3034 "Insert a modeline for module specification.
3035 This line should be first in the buffer.
3036 The module name should be written manually just before the semi-colon."
3038 (insert "%%% -*- Module: ; -*-\n")
3041 (defalias 'prolog-uncomment-region
3042 (if (fboundp 'uncomment-region
) #'uncomment-region
3044 "Uncomment the region between BEG and END."
3046 (comment-region beg end -
1))))
3048 (defun prolog-indent-predicate ()
3049 "Indent the current predicate."
3051 (indent-region (prolog-pred-start) (prolog-pred-end) nil
))
3053 (defun prolog-indent-buffer ()
3054 "Indent the entire buffer."
3056 (indent-region (point-min) (point-max) nil
))
3058 (defun prolog-mark-clause ()
3059 "Put mark at the end of this clause and move point to the beginning."
3061 (let ((pos (point)))
3062 (goto-char (prolog-clause-end))
3067 (goto-char (prolog-clause-start))))
3069 (defun prolog-mark-predicate ()
3070 "Put mark at the end of this predicate and move point to the beginning."
3072 (goto-char (prolog-pred-end))
3073 (let ((pos (point)))
3078 (goto-char (prolog-pred-start))))
3080 (defun prolog-electric--colon ()
3081 "If `prolog-electric-colon-flag' is non-nil, insert the electric `:' construct.
3082 That is, insert space (if appropriate), `:-' and newline if colon is pressed
3083 at the end of a line that starts in the first column (i.e., clause heads)."
3084 (when (and prolog-electric-colon-flag
3085 (eq (char-before) ?
:)
3086 (not current-prefix-arg
)
3088 (not (memq (char-after (line-beginning-position))
3090 (unless (memq (char-before (1- (point))) '(?\s ?
\t))
3091 (save-excursion (forward-char -
1) (insert " ")))
3093 (indent-according-to-mode)))
3095 (defun prolog-electric--dash ()
3096 "If `prolog-electric-dash-flag' is non-nil, insert the electric `-' construct.
3097 that is, insert space (if appropriate), `-->' and newline if dash is pressed
3098 at the end of a line that starts in the first column (i.e., DCG heads)."
3099 (when (and prolog-electric-dash-flag
3100 (eq (char-before) ?-
)
3101 (not current-prefix-arg
)
3103 (not (memq (char-after (line-beginning-position))
3105 (unless (memq (char-before (1- (point))) '(?\s ?
\t))
3106 (save-excursion (forward-char -
1) (insert " ")))
3108 (indent-according-to-mode)))
3110 (defun prolog-electric--dot ()
3111 "Make dot electric, if `prolog-electric-dot-flag' is non-nil.
3112 When invoked at the end of nonempty line, insert dot and newline.
3113 When invoked at the end of an empty line, insert a recursive call to
3114 the current predicate.
3115 When invoked at the beginning of line, insert a head of a new clause
3116 of the current predicate."
3117 ;; Check for situations when the electricity should not be active
3118 (if (or (not prolog-electric-dot-flag
)
3119 (not (eq (char-before) ?\.
))
3121 (nth 8 (syntax-ppss))
3122 ;; Do not be electric in a floating point number or an operator
3126 (skip-chars-backward " \t")
3127 (let ((num (> (skip-chars-backward "0-9") 0)))
3129 (memq (char-syntax (char-before))
3130 (if num
'(?w ?_
) '(?\
) ?w ?_
)))))))
3131 ;; Do not be electric if inside a parenthesis pair.
3132 (not (= (car (syntax-ppss))
3137 ;; Beginning of line
3138 ((save-excursion (forward-char -
1) (bolp))
3139 (delete-region (1- (point)) (point)) ;Delete the dot that called us.
3140 (prolog-insert-predicate-template))
3141 ;; At an empty line with at least one whitespace
3144 (looking-at "[ \t]+\\.$"))
3145 (delete-region (1- (point)) (point)) ;Delete the dot that called us.
3146 (prolog-insert-predicate-template)
3147 (when prolog-electric-dot-full-predicate-template
3156 (defun prolog-electric--underscore ()
3157 "Replace variable with an underscore.
3158 If `prolog-electric-underscore-flag' is non-nil and the point is
3159 on a variable then replace the variable with underscore and skip
3160 the following comma and whitespace, if any."
3161 (when prolog-electric-underscore-flag
3162 (let ((case-fold-search nil
))
3163 (when (and (not (nth 8 (syntax-ppss)))
3164 (eq (char-before) ?_
)
3166 (skip-chars-backward "[:alpha:]_")
3167 (looking-at "\\_<[_[:upper:]][[:alnum:]_]*\\_>")))
3169 (skip-chars-forward ", \t\n")))))
3171 (defun prolog-post-self-insert ()
3172 (pcase last-command-event
3173 (`?_
(prolog-electric--underscore))
3174 (`?-
(prolog-electric--dash))
3175 (`?
: (prolog-electric--colon))
3176 ((or `?\
( `?\
; `?>) (prolog-electric--if-then-else))
3177 (`?.
(prolog-electric--dot))))
3179 (defun prolog-find-term (functor arity
&optional prefix
)
3180 "Go to the position at the start of the next occurrence of a term.
3181 The term is specified with FUNCTOR and ARITY. The optional argument
3182 PREFIX is the prefix of the search regexp."
3183 (let* (;; If prefix is not set then use the default "\\<"
3184 (prefix (if (not prefix
)
3187 (regexp (concat prefix functor
))
3190 ;; Build regexp for the search if the arity is > 0
3192 ;; Add that the functor must be at the end of a word. This
3193 ;; does not work if the arity is > 0 since the closing )
3194 ;; is not a word constituent.
3195 (setq regexp
(concat regexp
"\\>"))
3196 ;; Arity is > 0, add parens and commas
3197 (setq regexp
(concat regexp
"("))
3199 (setq regexp
(concat regexp
".+,"))
3201 (setq regexp
(concat regexp
".+)")))
3203 ;; Search, and return position
3204 (if (re-search-forward regexp nil t
)
3205 (goto-char (match-beginning 0))
3206 (error "Term not found"))
3209 (defun prolog-variables-to-anonymous (beg end
)
3210 "Replace all variables within a region BEG to END by anonymous variables."
3213 (let ((case-fold-search nil
))
3215 (while (re-search-backward "\\<[A-Z_][a-zA-Z_0-9]*\\>" beg t
)
3221 ;;(defun prolog-regexp-dash-continuous-chars (chars)
3222 ;; (let ((ints (mapcar #'prolog-char-to-int (string-to-list chars)))
3227 ;; (while (and (< (+ beg 1) (length chars))
3228 ;; (not (or (= (+ (nth beg ints) 1) (nth (+ beg 1) ints))
3229 ;; (= (nth beg ints) (nth (+ beg 1) ints)))))
3230 ;; (setq beg (+ beg 1)))
3231 ;; (setq beg (+ beg 1)
3233 ;; (while (and (< (+ end 1) (length chars))
3234 ;; (or (= (+ (nth end ints) 1) (nth (+ end 1) ints))
3235 ;; (= (nth end ints) (nth (+ end 1) ints))))
3236 ;; (setq end (+ end 1)))
3237 ;; (if (equal (substring chars end) "")
3238 ;; (substring chars 0 beg)
3239 ;; (concat (substring chars 0 beg) "-"
3240 ;; (prolog-regexp-dash-continuous-chars (substring chars end))))
3243 ;;(defun prolog-condense-character-sets (regexp)
3244 ;; "Condense adjacent characters in character sets of REGEXP."
3246 ;; (while (setq next (string-match "\\[\\(.*?\\)\\]" regexp (1+ next)))
3247 ;; (setq regexp (replace-match (prolog-dash-letters (match-string 1 regexp))
3251 ;;-------------------------------------------------------------------
3252 ;; Menu stuff (both for the editing buffer and for the inferior
3254 ;;-------------------------------------------------------------------
3256 (unless (fboundp 'region-exists-p
)
3257 (defun region-exists-p ()
3258 "Non-nil if the mark is set. Lobotomized version for Emacsen that do not provide their own."
3262 ;; GNU Emacs ignores `easy-menu-add' so the order in which the menus
3263 ;; are defined _is_ important!
3266 prolog-menu-help
(list prolog-mode-map prolog-inferior-mode-map
)
3267 "Help menu for the Prolog mode."
3268 ;; FIXME: Does it really deserve a whole menu to itself?
3269 `(,(if (featurep 'xemacs
) "Help"
3270 ;; Not sure it's worth the trouble. --Stef
3271 ;; (add-to-list 'menu-bar-final-items
3272 ;; (easy-menu-intern "Prolog-Help"))
3274 ["On predicate" prolog-help-on-predicate prolog-help-function-i
]
3275 ["Apropos" prolog-help-apropos
(eq prolog-system
'swi
)]
3277 ["Describe mode" describe-mode t
]))
3280 prolog-edit-menu-runtime prolog-mode-map
3281 "Runtime Prolog commands available from the editing buffer"
3282 ;; FIXME: Don't use a whole menu for just "Run Mercury". --Stef
3284 ;; Runtime menu name.
3285 ,@(unless (featurep 'xemacs
)
3286 '(:label
(cond ((eq prolog-system
'eclipse
) "ECLiPSe")
3287 ((eq prolog-system
'mercury
) "Mercury")
3290 ;; Consult items, NIL for mercury.
3291 ["Consult file" prolog-consult-file
3292 :included
(not (eq prolog-system
'mercury
))]
3293 ["Consult buffer" prolog-consult-buffer
3294 :included
(not (eq prolog-system
'mercury
))]
3295 ["Consult region" prolog-consult-region
:active
(region-exists-p)
3296 :included
(not (eq prolog-system
'mercury
))]
3297 ["Consult predicate" prolog-consult-predicate
3298 :included
(not (eq prolog-system
'mercury
))]
3300 ;; Compile items, NIL for everything but SICSTUS.
3301 ,(if (featurep 'xemacs
) "---"
3302 ["---" nil
:included
(eq prolog-system
'sicstus
)])
3303 ["Compile file" prolog-compile-file
3304 :included
(eq prolog-system
'sicstus
)]
3305 ["Compile buffer" prolog-compile-buffer
3306 :included
(eq prolog-system
'sicstus
)]
3307 ["Compile region" prolog-compile-region
:active
(region-exists-p)
3308 :included
(eq prolog-system
'sicstus
)]
3309 ["Compile predicate" prolog-compile-predicate
3310 :included
(eq prolog-system
'sicstus
)]
3312 ;; Debug items, NIL for Mercury.
3313 ,(if (featurep 'xemacs
) "---"
3314 ["---" nil
:included
(not (eq prolog-system
'mercury
))])
3315 ;; FIXME: Could we use toggle or radio buttons? --Stef
3316 ["Debug" prolog-debug-on
:included
(not (eq prolog-system
'mercury
))]
3317 ["Debug off" prolog-debug-off
3318 ;; In SICStus, these are pairwise disjunctive,
3319 ;; so it's enough with a single "off"-command
3320 :included
(not (memq prolog-system
'(mercury sicstus
)))]
3321 ["Trace" prolog-trace-on
:included
(not (eq prolog-system
'mercury
))]
3322 ["Trace off" prolog-trace-off
3323 :included
(not (memq prolog-system
'(mercury sicstus
)))]
3324 ["Zip" prolog-zip-on
:included
(and (eq prolog-system
'sicstus
)
3325 (prolog-atleast-version '(3 .
7)))]
3326 ["All debug off" prolog-debug-off
3327 :included
(eq prolog-system
'sicstus
)]
3328 ["Source level debugging"
3329 prolog-toggle-sicstus-sd
3330 :included
(and (eq prolog-system
'sicstus
)
3331 (prolog-atleast-version '(3 .
7)))
3333 :selected prolog-use-sicstus-sd
]
3337 :suffix
(cond ((eq prolog-system
'eclipse
) "ECLiPSe")
3338 ((eq prolog-system
'mercury
) "Mercury")
3342 prolog-edit-menu-insert-move prolog-mode-map
3343 "Commands for Prolog code manipulation."
3345 ["Comment region" comment-region
(region-exists-p)]
3346 ["Uncomment region" prolog-uncomment-region
(region-exists-p)]
3347 ["Add comment/move to comment" indent-for-comment t
]
3348 ["Convert variables in region to '_'" prolog-variables-to-anonymous
3349 :active
(region-exists-p) :included
(not (eq prolog-system
'mercury
))]
3351 ["Insert predicate template" prolog-insert-predicate-template t
]
3352 ["Insert next clause head" prolog-insert-next-clause t
]
3353 ["Insert predicate spec" prolog-insert-predspec t
]
3354 ["Insert module modeline" prolog-insert-module-modeline t
]
3356 ["Beginning of clause" prolog-beginning-of-clause t
]
3357 ["End of clause" prolog-end-of-clause t
]
3358 ["Beginning of predicate" prolog-beginning-of-predicate t
]
3359 ["End of predicate" prolog-end-of-predicate t
]
3361 ["Indent line" indent-according-to-mode t
]
3362 ["Indent region" indent-region
(region-exists-p)]
3363 ["Indent predicate" prolog-indent-predicate t
]
3364 ["Indent buffer" prolog-indent-buffer t
]
3365 ["Align region" align
(region-exists-p)]
3367 ["Mark clause" prolog-mark-clause t
]
3368 ["Mark predicate" prolog-mark-predicate t
]
3369 ["Mark paragraph" mark-paragraph t
]
3372 (defun prolog-menu ()
3373 "Add the menus for the Prolog editing buffers."
3375 (easy-menu-add prolog-edit-menu-insert-move
)
3376 (easy-menu-add prolog-edit-menu-runtime
)
3378 ;; Add predicate index menu
3379 (setq-local imenu-create-index-function
3380 'imenu-default-create-index-function
)
3381 ;;Milan (this has problems with object methods...) ###### Does it? (Stefan)
3382 (setq-local imenu-prev-index-position-function
3383 #'prolog-beginning-of-predicate
)
3384 (setq-local imenu-extract-index-name-function
#'prolog-get-predspec
)
3386 (if (and prolog-imenu-flag
3387 (< (count-lines (point-min) (point-max)) prolog-imenu-max-lines
))
3388 (imenu-add-to-menubar "Predicates"))
3390 (easy-menu-add prolog-menu-help
))
3393 prolog-inferior-menu-all prolog-inferior-mode-map
3394 "Menu for the inferior Prolog buffer."
3396 ;; Runtime menu name.
3397 ,@(unless (featurep 'xemacs
)
3398 '(:label
(cond ((eq prolog-system
'eclipse
) "ECLiPSe")
3399 ((eq prolog-system
'mercury
) "Mercury")
3402 ;; Debug items, NIL for Mercury.
3403 ,(if (featurep 'xemacs
) "---"
3404 ["---" nil
:included
(not (eq prolog-system
'mercury
))])
3405 ;; FIXME: Could we use toggle or radio buttons? --Stef
3406 ["Debug" prolog-debug-on
:included
(not (eq prolog-system
'mercury
))]
3407 ["Debug off" prolog-debug-off
3408 ;; In SICStus, these are pairwise disjunctive,
3409 ;; so it's enough with a single "off"-command
3410 :included
(not (memq prolog-system
'(mercury sicstus
)))]
3411 ["Trace" prolog-trace-on
:included
(not (eq prolog-system
'mercury
))]
3412 ["Trace off" prolog-trace-off
3413 :included
(not (memq prolog-system
'(mercury sicstus
)))]
3414 ["Zip" prolog-zip-on
:included
(and (eq prolog-system
'sicstus
)
3415 (prolog-atleast-version '(3 .
7)))]
3416 ["All debug off" prolog-debug-off
3417 :included
(eq prolog-system
'sicstus
)]
3418 ["Source level debugging"
3419 prolog-toggle-sicstus-sd
3420 :included
(and (eq prolog-system
'sicstus
)
3421 (prolog-atleast-version '(3 .
7)))
3423 :selected prolog-use-sicstus-sd
]
3427 ["Interrupt Prolog" comint-interrupt-subjob t
]
3428 ["Quit Prolog" comint-quit-subjob t
]
3429 ["Kill Prolog" comint-kill-subjob t
]))
3432 (defun prolog-inferior-menu ()
3433 "Create the menus for the Prolog inferior buffer.
3434 This menu is dynamically created because one may change systems during
3435 the life of an Emacs session."
3436 (easy-menu-add prolog-inferior-menu-all
)
3437 (easy-menu-add prolog-menu-help
))
3439 (defun prolog-mode-version ()
3440 "Echo the current version of Prolog mode in the minibuffer."
3442 (message "Using Prolog mode version %s" prolog-mode-version
))
3446 ;;; prolog.el ends here