-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathprolog.el
More file actions
4216 lines (3833 loc) · 157 KB
/
prolog.el
File metadata and controls
4216 lines (3833 loc) · 157 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
;; prolog.el --- major mode for editing and running Prolog (and Mercury) code
;; Copyright (C) 1986, 1987, 1997, 1998, 1999, 2002, 2003 Free Software Foundation, Inc.
;; Authors: Emil �str�m <emil_astrom(at)hotmail(dot)com>
;; Milan Zamazal <pdm(at)freesoft(dot)cz>
;; Stefan Bruda <stefan(at)bruda(dot)ca> (current maintainer)
;; Eyal Dechter <eyaldechter@gmail.com>
;; * See below for more details
;; Keywords: prolog major mode sicstus swi mercury yap
(defvar prolog-mode-version "1.26"
"Prolog mode version number")
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs; see the file COPYING. If not, write to the
;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.
;; Original author: Masanobu UMEDA <umerin(at)mse(dot)kyutech(dot)ac(dot)jp>
;; Parts of this file was taken from a modified version of the original
;; by Johan Andersson, Peter Olin, Mats Carlsson, Johan Bevemyr, Stefan
;; Andersson, and Per Danielsson (all SICS people), and Henrik B�kman
;; at Uppsala University, Sweden.
;;
;; Some ideas and also a few lines of code have been borrowed (not stolen ;-)
;; from Oz.el, the Emacs major mode for the Oz programming language,
;; Copyright (C) 1993 DFKI GmbH, Germany, with permission.
;; Authors: Ralf Scheidhauer and Michael Mehl ([scheidhr|mehl](at)dfki(dot)uni-sb(dot)de)
;;
;; More ideas and code have been taken from the SICStus debugger mode
;; (http://www.csd.uu.se/~perm/source_debug/index.shtml -- broken link
;; as of Mon May 5 08:23:48 EDT 2003) by Per Mildner.
;;
;; Additions for ECLiPSe and other helpful suggestions: Stephan Heuel
;; <heuel(at)ipb(dot)uni-bonn(dot)de>
;;
;; This fork of prolog.el is maintained by Eyal Dechter
;; <eyaldechter(at)gmail(dot)com>
;;; Commentary:
;;
;; This package provides a major mode for editing Prolog code, with
;; all the bells and whistles one would expect, including syntax
;; highlighting and auto indentation. It can also send regions to an
;; inferior Prolog process.
;;
;; The code requires the comint, easymenu, info, imenu, and font-lock
;; libraries. These are normally distributed with GNU Emacs and
;; XEmacs.
;;; Installation:
;;
;; Insert the following lines in your init file--typically ~/.emacs
;; (GNU Emacs and XEmacs <21.4), or ~/.xemacs/init.el (XEmacs
;; 21.4)--to use this mode when editing Prolog files under Emacs:
;;
;; (setq load-path (cons "/usr/lib/xemacs/site-lisp" load-path))
;; (autoload 'run-prolog "prolog" "Start a Prolog sub-process." t)
;; (autoload 'prolog-mode "prolog" "Major mode for editing Prolog programs." t)
;; (autoload 'mercury-mode "prolog" "Major mode for editing Mercury programs." t)
;; (setq prolog-system 'swi) ; optional, the system you are using;
;; ; see `prolog-system' below for possible values
;; (setq auto-mode-alist (append '(("\\.pl$" . prolog-mode)
;; ("\\.m$" . mercury-mode))
;; auto-mode-alist))
;;
;; where the path in the first line is the file system path to this file.
;; MSDOS paths can be written like "d:/programs/emacs-19.34/site-lisp".
;; Note: In XEmacs, either `/usr/lib/xemacs/site-lisp' (RPM default in
;; Red Hat-based distributions) or `/usr/local/lib/xemacs/site-lisp'
;; (default when compiling from sources) are automatically added to
;; `load-path', so the first line is not necessary provided that you
;; put this file in the appropriate place.
;;
;; The last s-expression above makes sure that files ending with .pl
;; are assumed to be Prolog files and not Perl, which is the default
;; Emacs setting. If this is not wanted, remove this line. It is then
;; necessary to either
;;
;; o insert in your Prolog files the following comment as the first line:
;;
;; % -*- Mode: Prolog -*-
;;
;; and then the file will be open in Prolog mode no matter its
;; extension, or
;;
;; o manually switch to prolog mode after opening a Prolog file, by typing
;; M-x prolog-mode.
;;
;; If the command to start the prolog process ('sicstus', 'pl' or
;; 'swipl' for SWI prolog, etc.) is not available in the default path,
;; then it is necessary to set the value of the environment variable
;; EPROLOG to a shell command to invoke the prolog process. In XEmacs
;; and Emacs 20+ you can also customize the variable
;; `prolog-program-name' (in the group `prolog-inferior') and provide
;; a full path for your Prolog system (swi, scitus, etc.).
;;
;; Note: I (Stefan, the current maintainer) work under XEmacs. Future
;; developments will thus be biased towards XEmacs (OK, I admit it,
;; I am biased towards XEmacs in general), though I will do my best
;; to keep the GNU Emacs compatibility. So if you work under Emacs
;; and see something that does not work do drop me a line, as I have
;; a smaller chance to notice this kind of bugs otherwise.
;; Changelog:
;; Version 1.25:
;; o ANSI escape sequences are now taken into account (requires
;; "ansi-color"), in the sense that they are either translated
;; into text properties or ignored. The default, non-nil value of
;; the customizable variables `prolog-inferior-ansi-color' causes
;; the translation of ANSI escape sequences; set the variable to
;; nil to ignore them instead.
;; Version 1.24:
;; o GNU Prolog and YAP can now be chosen in the customization menu
;; (previously only SWI and SICSTUS could be chosen). Patch by
;; Jeronimo Pellegrini.
;; Version 1.23:
;; o Added support for XSB <http://xsb.sourceforge.net>; trivial
;; adaptation of a patch by Spyros Hadjichristodoulou and Cosmin
;; Munteanu
;; Version 1.22:
;; o Allowed both 'swipl' and 'pl' as names for the SWI Prolog
;; interpreter.
;; o Atoms that start a line are not blindly coloured as
;; predicates. Instead we check that they are followed by ( or
;; :- first. Patch suggested by Guy Wiener.
;; Version 1.21:
;; o Cleaned up the code that defines faces. The missing face
;; warnings on some Emacsen should disappear.
;; Version 1.20:
;; o Improved the handling of clause start detection and multi-line
;; comments: `prolog-clause-start' no longer finds non-predicate
;; (e.g., capitalized strings) beginning of clauses.
;; o `prolog-tokenize' recognizes when the end point is within a
;; multi-line comment.
;; Version 1.19:
;; o Minimal changes for Aquamacs inclusion and in general for
;; better coping with finding the Prolog executable. Patch
;; provided by David Reitter
;; Version 1.18:
;; o Fixed syntax highlighting for clause heads that do not begin at
;; the beginning of the line.
;; o Fixed compilation warnings under Emacs.
;; o Updated the email address of the current maintainer.
;; Version 1.17:
;; o Minor indentation fix (patch by Markus Triska)
;; o `prolog-underscore-wordchar-flag' defaults now to nil (more
;; consistent to other Emacs modes)
;; Version 1.16:
;; o Eliminated a possible compilation warning.
;; Version 1.15:
;; o Introduced three new customizable variables: electric colon
;; (`prolog-electric-colon-flag', default nil), electric dash
;; (`prolog-electric-dash-flag', default nil), and a possibility
;; to prevent the predicate template insertion from adding commata
;; (`prolog-electric-dot-full-predicate-template', defaults to t
;; since it seems quicker to me to just type those commata). A
;; trivial adaptation of a patch by Markus Triska.
;; o Improved the behaviour of electric if-then-else to only skip
;; forward if the parenthesis/semicolon is preceded by
;; whitespace. Once more a trivial adaptation of a patch by
;; Markus Triska.
;; Version 1.14:
;; o Cleaned up align code. `prolog-align-flag' is eliminated (since
;; on a second thought it does not do anything useful). Added key
;; binding (C-c C-a) and menu entry for alignment.
;; o Condensed regular expressions for lower and upper case
;; characters (GNU Emacs seems to go over the regexp length limit
;; with the original form). My code on the matter was improved
;; considerably by Markus Triska.
;; o Fixed `prolog-insert-spaces-after-paren' (which used an
;; unitialized variable).
;; o Minor changes to clean up the code and avoid some implicit
;; package requirements.
;; Version 1.13:
;; o Removed the use of `map-char-table' in `prolog-build-case-strings'
;; which appears to cause prblems in (at least) Emacs 23.0.0.1.
;; o Added if-then-else indentation + corresponding electric
;; characters. New customization: `prolog-electric-if-then-else-flag'
;; o Align support (requires `align'). New customization:
;; `prolog-align-flag'.
;; o Temporary consult files have now the same name throughout the
;; session. This prevents issues with reconsulting a buffer
;; (this event is no longer passed to Prolog as a request to
;; consult a new file).
;; o Adaptive fill mode is now turned on. Comment indentation is
;; still worse than it could be though, I am working on it.
;; o Improved filling and auto-filling capabilities. Now block
;; comments should be [auto-]filled correctly most of the time;
;; the following pattern in particular is worth noting as being
;; filled correctly:
;; <some code here> % some comment here that goes beyond the
;; % rightmost column, possibly combined with
;; % subsequent comment lines
;; o `prolog-char-quote-workaround' now defaults to nil.
;; o Note: Many of the above improvements have been suggested by
;; Markus Triska, who also provided useful patches on the matter
;; when he realized that I was slow in responding. Many thanks.
;; Version 1.11 / 1.12
;; o GNU Emacs compatibility fix for paragraph filling (fixed
;; incorrectly in 1.11, fix fixed in 1.12).
;; Version 1.10
;; o Added paragraph filling in comment blocks and also correct auto
;; filling for comments.
;; o Fixed the possible "Regular expression too big" error in
;; `prolog-electric-dot'.
;; Version 1.9
;; o Parenthesis expressions are now indented by default so that
;; components go one underneath the other, just as for compound
;; terms. You can use the old style (the second and subsequent
;; lines being indented to the right in a parenthesis expression)
;; by setting the customizable variable `prolog-paren-indent-p'
;; (group "Prolog Indentation") to t.
;; o (Somehow awkward) handling of the 0' character escape
;; sequence. I am looking into a better way of doing it but
;; prospects look bleak. If this breaks things for you please let
;; me know and also set the `prolog-char-quote-workaround' (group
;; "Prolog Other") to nil.
;; Version 1.8
;; o Key binding fix.
;; Version 1.7
;; o Fixed a number of issues with the syntax of single quotes,
;; including Debian bug #324520.
;; Version 1.6
;; o Fixed mercury mode menu initialization (Debian bug #226121).
;; o Fixed (i.e., eliminated) Delete remapping (Debian bug #229636).
;; o Corrected indentation for clauses defining quoted atoms.
;; Version 1.5:
;; o Keywords fontifying should work in console mode so this is
;; enabled everywhere.
;; Version 1.4:
;; o Now supports GNU Prolog--minor adaptation of a patch by Stefan
;; Moeding.
;; Version 1.3:
;; o Info-follow-nearest-node now called correctly under Emacs too
;; (thanks to Nicolas Pelletier). Should be implemented more
;; elegantly (i.e., without compilation warnings) in the future.
;; Version 1.2:
;; o Another prompt fix, still in SWI mode (people seem to have
;; changed the prompt of SWI Prolog).
;; Version 1.1:
;; o Fixed dots in the end of line comments causing indentation
;; problems. The following code is now correctly indented (note
;; the dot terminating the comment):
;; a(X) :- b(X),
;; c(X). % comment here.
;; a(X).
;; and so is this (and variants):
;; a(X) :- b(X),
;; c(X). /* comment here. */
;; a(X).
;; Version 1.0:
;; o Revamped the menu system.
;; o Yet another prompt recognition fix (SWI mode).
;; o This is more of a renumbering than a new edition. I promoted
;; the mode to version 1.0 to emphasize the fact that it is now
;; mature and stable enough to be considered production (in my
;; opinion anyway).
;; Version 0.1.41:
;; o GNU Emacs compatibility fixes.
;; Version 0.1.40:
;; o prolog-get-predspec is now suitable to be called as
;; imenu-extract-index-name-function. The predicate index works.
;; o Since imenu works now as advertised, prolog-imenu-flag is t
;; by default.
;; o Eliminated prolog-create-predicate-index since the imenu
;; utilities now work well. Actually, this function is also
;; buggy, and I see no reason to fix it since we do not need it
;; anyway.
;; o Fixed prolog-pred-start, prolog-clause-start, prolog-clause-info.
;; o Fix for prolog-build-case-strings; now prolog-upper-case-string
;; and prolog-lower-case-string are correctly initialized,
;; o Various font-lock changes; most importantly, block comments (/*
;; ... */) are now correctly fontified in XEmacs even when they
;; extend on multiple lines.
;; Version 0.1.36:
;; o The debug prompt of SWI Prolog is now correctly recognized.
;; Version 0.1.35:
;; o Minor font-lock bug fixes.
;;; Code:
(eval-when-compile
(require 'compile)
(require 'font-lock)
;; We need imenu everywhere because of the predicate index!
(require 'imenu)
(require 'info)
(require 'shell)
)
(require 'comint)
(require 'easymenu)
(require 'align)
(require 'ansi-color)
(defgroup prolog nil
"Major modes for editing and running Prolog and Mercury files."
:group 'languages)
(defgroup prolog-faces nil
"Prolog mode specific faces."
:group 'font-lock)
(defgroup prolog-indentation nil
"Prolog mode indentation configuration."
:group 'prolog)
(defgroup prolog-font-lock nil
"Prolog mode font locking patterns."
:group 'prolog)
(defgroup prolog-keyboard nil
"Prolog mode keyboard flags."
:group 'prolog)
(defgroup prolog-inferior nil
"Inferior Prolog mode options."
:group 'prolog)
(defgroup prolog-other nil
"Other Prolog mode options."
:group 'prolog)
;;-------------------------------------------------------------------
;; User configurable variables
;;-------------------------------------------------------------------
;; General configuration
(defcustom prolog-system nil
"*Prolog interpreter/compiler used.
The value of this variable is nil or a symbol.
If it is a symbol, it determines default values of other configuration
variables with respect to properties of the specified Prolog
interpreter/compiler.
Currently recognized symbol values are:
eclipse - Eclipse Prolog
mercury - Mercury
sicstus - SICStus Prolog
swi - SWI Prolog
xsb - XSB <http://xsb.sourceforge.net>
gnu - GNU Prolog
yap - YAP Prolog"
:group 'prolog
:type '(choice (const :tag "SICStus" :value sicstus)
(const :tag "SWI Prolog" :value swi)
(const :tag "GNU Prolog" :value gnu)
(const :tag "YAP" :value yap)
(const :tag "Default" :value nil)))
(make-variable-buffer-local 'prolog-system)
;; NB: This alist can not be processed in prolog-mode-variables to
;; create a prolog-system-version-i variable since it is needed
;; prior to the call to prolog-mode-variables.
(defcustom prolog-system-version
'((sicstus (3 . 6))
(swi (0 . 0))
(mercury (0 . 0))
(eclipse (3 . 7))
(gnu (0 . 0)))
"*Alist of Prolog system versions.
The version numbers are of the format (Major . Minor)."
:group 'prolog)
;; Indentation
(defcustom prolog-indent-width tab-width
"*The indentation width used by the editing buffer."
:group 'prolog-indentation
:type 'integer)
(defcustom prolog-align-comments-flag t
"*Non-nil means automatically align comments when indenting."
:group 'prolog-indentation
:type 'boolean)
(defcustom prolog-indent-mline-comments-flag t
"*Non-nil means indent contents of /* */ comments.
Otherwise leave such lines as they are."
:group 'prolog-indentation
:type 'boolean)
(defcustom prolog-object-end-to-0-flag t
"*Non-nil means indent closing '}' in SICStus object definitions to level 0.
Otherwise indent to `prolog-indent-width'."
:group 'prolog-indentation
:type 'boolean)
(defcustom prolog-left-indent-regexp "\\(;\\|\\*?->\\)"
"*Regexp for character sequences after which next line is indented.
Next line after such a regexp is indented to the opening paranthesis level."
:group 'prolog-indentation
:type 'regexp)
(defcustom prolog-paren-indent-p nil
"*If non-nil, increase indentation for parenthesis expressions.
The second and subsequent line in a parenthesis expression other than
a compound term can either be indented `prolog-paren-indent' to the
right (if this variable is non-nil) or in the same way as for compound
terms (if this variable is nil, default)."
:group 'prolog-indentation
:type 'boolean)
(defcustom prolog-paren-indent 4
"*The indentation increase for parenthesis expressions.
Only used in ( If -> Then ; Else) and ( Disj1 ; Disj2 ) style expressions."
:group 'prolog-indentation
:type 'integer)
(defcustom prolog-parse-mode 'beg-of-clause
"*The parse mode used (decides from which point parsing is done).
Legal values:
'beg-of-line - starts parsing at the beginning of a line, unless the
previous line ends with a backslash. Fast, but has
problems detecting multiline /* */ comments.
'beg-of-clause - starts parsing at the beginning of the current clause.
Slow, but copes better with /* */ comments."
:group 'prolog-indentation
:type '(choice (const :value beg-of-line)
(const :value beg-of-clause)))
;; Font locking
(defcustom prolog-keywords
'((eclipse
("use_module" "begin_module" "module_interface" "dynamic"
"external" "export" "dbgcomp" "nodbgcomp" "compile"))
(mercury
("all" "else" "end_module" "equality" "external" "fail" "func" "if"
"implementation" "import_module" "include_module" "inst" "instance"
"interface" "mode" "module" "not" "pragma" "pred" "some" "then" "true"
"type" "typeclass" "use_module" "where"))
(sicstus
("block" "dynamic" "mode" "module" "multifile" "meta_predicate"
"parallel" "public" "sequential" "volatile"))
(swi
("discontiguous" "dynamic" "ensure_loaded" "export" "export_list" "import"
"meta_predicate" "module" "module_transparent" "multifile" "require"
"use_module" "volatile"))
(gnu
("built_in" "char_conversion" "discontiguous" "dynamic" "ensure_linked"
"ensure_loaded" "foreign" "include" "initialization" "multifile" "op"
"public" "set_prolog_flag"))
(xsb
("dynamic" "import" "export" "from" "table" "auto_table" "ti" "multifile"
"true" "fail"))
(t
("dynamic" "module")))
"*Alist of Prolog keywords which is used for font locking of directives."
:group 'prolog-font-lock
:type 'sexp)
(defcustom prolog-types
'((mercury
("char" "float" "int" "io__state" "string" "univ"))
(t nil))
"*Alist of Prolog types used by font locking."
:group 'prolog-font-lock
:type 'sexp)
(defcustom prolog-mode-specificators
'((mercury
("bound" "di" "free" "ground" "in" "mdi" "mui" "muo" "out" "ui" "uo"))
(t nil))
"*Alist of Prolog mode specificators used by font locking."
:group 'prolog-font-lock
:type 'sexp)
(defcustom prolog-determinism-specificators
'((mercury
("cc_multi" "cc_nondet" "det" "erroneous" "failure" "multi" "nondet"
"semidet"))
(t nil))
"*Alist of Prolog determinism specificators used by font locking."
:group 'prolog-font-lock
:type 'sexp)
(defcustom prolog-directives
'((mercury
("^#[0-9]+"))
(t nil))
"*Alist of Prolog source code directives used by font locking."
:group 'prolog-font-lock
:type 'sexp)
;; Keyboard
(defcustom prolog-electric-newline-flag t
"*Non-nil means automatically indent the next line when the user types RET."
:group 'prolog-keyboard
:type 'boolean)
(defcustom prolog-hungry-delete-key-flag nil
"*Non-nil means delete key consumes all preceding spaces."
:group 'prolog-keyboard
:type 'boolean)
(defcustom prolog-electric-dot-flag nil
"*Non-nil means make dot key electric.
Electric dot appends newline or inserts head of a new clause.
If dot is pressed at the end of a line where at least one white space
precedes the point, it inserts a recursive call to the current predicate.
If dot is pressed at the beginning of an empty line, it inserts the head
of a new clause for the current predicate. It does not apply in strings
and comments.
It does not apply in strings and comments."
:group 'prolog-keyboard
:type 'boolean)
(defcustom prolog-electric-dot-full-predicate-template nil
"*If nil, electric dot inserts only the current predicate's name and `('
for recursive calls or new clause heads. Non-nil means to also
insert enough commata to cover the predicate's arity and `)',
and dot and newline for recursive calls."
:group 'prolog-keyboard
:type 'boolean)
(defcustom prolog-electric-underscore-flag nil
"*Non-nil means make underscore key electric.
Electric underscore replaces the current variable with underscore.
If underscore is pressed not on a variable then it behaves as usual."
:group 'prolog-keyboard
:type 'boolean)
(defcustom prolog-electric-tab-flag nil
"*Non-nil means make TAB key electric.
Electric TAB inserts spaces after parentheses, ->, and ;
in ( If -> Then ; Else) and ( Disj1 ; Disj2 ) style expressions."
:group 'prolog-keyboard
:type 'boolean)
(defcustom prolog-electric-if-then-else-flag nil
"*Non-nil makes `(', `>' and `;' electric
to automatically indent if-then-else constructs."
:group 'prolog-keyboard
:type 'boolean)
(defcustom prolog-electric-colon-flag nil
"*Makes `:' electric (inserts `:-' on a new line).
If non-nil, pressing `:' at the end of a line that starts in
the first column (i.e., clause heads) inserts ` :-' and newline."
:group 'prolog-keyboard
:type 'boolean)
(defcustom prolog-electric-dash-flag nil
"*Makes `-' electric (inserts a `-->' on a new line).
If non-nil, pressing `-' at the end of a line that starts in
the first column (i.e., DCG heads) inserts ` -->' and newline."
:group 'prolog-keyboard
:type 'boolean)
(defcustom prolog-old-sicstus-keys-flag nil
"*Non-nil means old SICStus Prolog mode keybindings are used."
:group 'prolog-keyboard
:type 'boolean)
;; Inferior mode
(defcustom prolog-program-name
`(((getenv "EPROLOG") (eval (getenv "EPROLOG")))
(eclipse "eclipse")
(mercury nil)
(sicstus "sicstus")
(swi ,(if (not (executable-find "swipl")) "pl" "swipl"))
(gnu "gprolog")
(yap "yap")
(xsb "xsb")
(t ,(let ((names '("prolog" "gprolog" "swipl" "pl")))
(while (and names
(not (executable-find (car names))))
(setq names (cdr names)))
(or (car names) "prolog"))))
"*Alist of program names for invoking an inferior Prolog with `run-prolog'."
:group 'prolog-inferior
:type 'sexp)
(defcustom prolog-program-switches
'((sicstus ("-i"))
(t nil))
"*Alist of switches given to inferior Prolog run with `run-prolog'."
:group 'prolog-inferior
:type 'sexp)
(defcustom prolog-inferior-ansi-color
t
"*Whether to translate ANSI escape sequences of filter them out.
If non-nil (default) then the ANSI escape sequneces are translated
into text properties, otherwise the escape sequences are filtered out.
Obviously this option has no effect if the inferior Prolog interpreter
does not use ANSI escape sequences."
:group 'prolog-inferior
:type 'sexp)
(defcustom prolog-consult-string
'((eclipse "[%f].")
(mercury nil)
(sicstus (eval (if (prolog-atleast-version '(3 . 7))
"prolog:zap_file(%m,%b,consult,%l)."
"prolog:zap_file(%m,%b,consult).")))
(swi "[%f].")
;; (swi "load_files([%f], [redefine_module(true)]).")
(gnu "[%f].")
(xsb "[%f].")
(yap "[%f].")
(t "reconsult(%f)."))
"*Alist of strings defining predicate for reconsulting.
Some parts of the string are replaced:
`%f' by the name of the consulted file (can be a temporary file)
`%b' by the file name of the buffer to consult
`%m' by the module name and name of the consulted file separated by colon
`%l' by the line offset into the file. This is 0 unless consulting a
region of a buffer, in which case it is the number of lines before
the region."
:group 'prolog-inferior
:type 'sexp)
(defcustom prolog-compile-string
'((eclipse "[%f].")
(mercury "mmake ")
(sicstus (eval (if (prolog-atleast-version '(3 . 7))
"prolog:zap_file(%m,%b,compile,%l)."
"prolog:zap_file(%m,%b,compile).")))
(swi "[%f].")
(t "compile(%f)."))
"*Alist of strings and lists defining predicate for recompilation.
Some parts of the string are replaced:
`%f' by the name of the compiled file (can be a temporary file)
`%b' by the file name of the buffer to compile
`%m' by the module name and name of the compiled file separated by colon
`%l' by the line offset into the file. This is 0 unless compiling a
region of a buffer, in which case it is the number of lines before
the region.
If `prolog-program-name' is non-nil, it is a string sent to a Prolog process.
If `prolog-program-name' is nil, it is an argument to the `compile' function."
:group 'prolog-inferior
:type 'sexp)
(defcustom prolog-eof-string "end_of_file.\n"
"*Alist of strings that represent end of file for prolog.
nil means send actual operating system end of file."
:group 'prolog-inferior
:type 'sexp)
(defcustom prolog-prompt-regexp
'((eclipse "^[a-zA-Z0-9()]* *\\?- \\|^\\[[a-zA-Z]* [0-9]*\\]:")
(sicstus "| [ ?][- ] *")
(swi "^\\(\\[[a-zA-Z]*\\] \\)?[1-9]?[0-9]*[ ]?\\?- \\|^| +")
(t "^ *\\?-"))
"*Alist of prompts of the prolog system command line."
:group 'prolog-inferior
:type 'sexp)
(defcustom prolog-continued-prompt-regexp
'((sicstus "^\\(| +\\| +\\)")
(t "^|: +"))
"*Alist of regexps matching the prompt when consulting `user'."
:group 'prolog-inferior
:type 'sexp)
(defcustom prolog-debug-on-string "debug.\n"
"*Predicate for enabling debug mode."
:group 'prolog-inferior
:type 'string)
(defcustom prolog-debug-off-string "nodebug.\n"
"*Predicate for disabling debug mode."
:group 'prolog-inferior
:type 'string)
(defcustom prolog-trace-on-string "trace.\n"
"*Predicate for enabling tracing."
:group 'prolog-inferior
:type 'string)
(defcustom prolog-trace-off-string "notrace.\n"
"*Predicate for disabling tracing."
:group 'prolog-inferior
:type 'string)
(defcustom prolog-zip-on-string "zip.\n"
"*Predicate for enabling zip mode for SICStus."
:group 'prolog-inferior
:type 'string)
(defcustom prolog-zip-off-string "nozip.\n"
"*Predicate for disabling zip mode for SICStus."
:group 'prolog-inferior
:type 'string)
(defcustom prolog-use-standard-consult-compile-method-flag t
"*Non-nil means use the standard compilation method.
Otherwise the new compilation method will be used. This
utilises a special compilation buffer with the associated
features such as parsing of error messages and automatically
jumping to the source code responsible for the error.
Warning: the new method is so far only experimental and
does contain bugs. The recommended setting for the novice user
is non-nil for this variable."
:group 'prolog-inferior
:type 'boolean)
;; Miscellaneous
(defcustom prolog-use-prolog-tokenizer-flag t
"*Non-nil means use the internal prolog tokenizer for indentation etc.
Otherwise use `parse-partial-sexp' which is faster but sometimes incorrect."
:group 'prolog-other
:type 'boolean)
(defcustom prolog-imenu-flag t
"*Non-nil means add a clause index menu for all prolog files."
:group 'prolog-other
:type 'boolean)
(defcustom prolog-imenu-max-lines 3000
"*The maximum number of lines of the file for imenu to be enabled.
Relevant only when `prolog-imenu-flag' is non-nil."
:group 'prolog-other
:type 'integer)
(defcustom prolog-info-predicate-index
"(sicstus)Predicate Index"
"*The info node for the SICStus predicate index."
:group 'prolog-other
:type 'string)
(defcustom prolog-underscore-wordchar-flag nil
"*Non-nil means underscore (_) is a word-constituent character."
:group 'prolog-other
:type 'boolean)
(defcustom prolog-use-sicstus-sd nil
"*If non-nil, use the source level debugger of SICStus 3#7 and later."
:group 'prolog-other
:type 'boolean)
(defcustom prolog-char-quote-workaround nil
"*If non-nil, declare 0 as a quote character so that 0'<char> does not break syntax highlighting.
This is really kludgy but I have not found any better way of handling it."
:group 'prolog-other
:type 'boolean)
;;-------------------------------------------------------------------
;; Internal variables
;;-------------------------------------------------------------------
(defvar prolog-emacs
(if (string-match "XEmacs\\|Lucid" emacs-version)
'xemacs
'gnuemacs)
"The variant of Emacs we're running.
Valid values are 'gnuemacs and 'xemacs.")
(defvar prolog-known-systems '(eclipse mercury sicstus swi gnu xsb yap))
;(defvar prolog-temp-filename "") ; Later set by `prolog-temporary-file'
(defvar prolog-mode-syntax-table nil)
(defvar prolog-mode-abbrev-table nil)
(defvar prolog-mode-map nil)
(defvar prolog-upper-case-string ""
"A string containing all upper case characters.
Set by prolog-build-case-strings.")
(defvar prolog-lower-case-string ""
"A string containing all lower case characters.
Set by prolog-build-case-strings.")
(defvar prolog-atom-char-regexp ""
"Set by prolog-set-atom-regexps.")
;; "Regexp specifying characters which constitute atoms without quoting.")
(defvar prolog-atom-regexp ""
"Set by prolog-set-atom-regexps.")
(defconst prolog-left-paren "[[({]"
"The characters used as left parentheses for the indentation code.")
(defconst prolog-right-paren "[])}]"
"The characters used as right parentheses for the indentation code.")
(defconst prolog-quoted-atom-regexp
"\\(^\\|[^0-9]\\)\\('\\([^\n']\\|\\\\'\\)*'\\)"
"Regexp matching a quoted atom.")
(defconst prolog-quoted-or-unquoted-atom-regexp
(format "\\(%s\\|%s\\)" prolog-quoted-atom-regexp prolog-atom-regexp))
(defconst prolog-string-regexp
"\\(\"\\([^\n\"]\\|\\\\\"\\)*\"\\)"
"Regexp matching a string.")
(defconst prolog-head-delimiter "\\(:-\\|\\+:\\|-:\\|\\+\\?\\|-\\?\\|-->\\)"
"A regexp for matching on the end delimiter of a head (e.g. \":-\").")
(defvar prolog-compilation-buffer "*prolog-compilation*"
"Name of the output buffer for Prolog compilation/consulting.")
(defvar prolog-temporary-file-name nil)
(defvar prolog-keywords-i nil)
(defvar prolog-types-i nil)
(defvar prolog-mode-specificators-i nil)
(defvar prolog-determinism-specificators-i nil)
(defvar prolog-directives-i nil)
(defvar prolog-program-name-i nil)
(defvar prolog-program-switches-i nil)
(defvar prolog-consult-string-i nil)
(defvar prolog-compile-string-i nil)
(defvar prolog-eof-string-i nil)
(defvar prolog-prompt-regexp-i nil)
(defvar prolog-continued-prompt-regexp-i nil)
(defvar prolog-help-function-i nil)
(defvar prolog-align-rules
(eval-when-compile
(mapcar
(lambda (x)
(let ((name (car x))
(sym (cdr x)))
`(,(intern (format "prolog-%s" name))
(regexp . ,(format "\\(\\s-*\\)%s\\(\\s-*\\)" sym))
(tab-stop . nil)
(modes . '(prolog-mode))
(group . (1 2)))))
'(("dcg" . "-->") ("rule" . ":-") ("simplification" . "<=>")
("propagation" . "==>")))))
;;-------------------------------------------------------------------
;; Prolog mode
;;-------------------------------------------------------------------
;; Example: (prolog-atleast-version '(3 . 6))
(defun prolog-atleast-version (version)
"Return t if the version of the current prolog system is VERSION or later.
VERSION is of the format (Major . Minor)"
;; Version.major < major or
;; Version.major = major and Version.minor <= minor
(let* ((thisversion (prolog-find-value-by-system prolog-system-version))
(thismajor (car thisversion))
(thisminor (cdr thisversion)))
(or (< (car version) thismajor)
(and (= (car version) thismajor)
(<= (cdr version) thisminor)))
))
(if prolog-mode-syntax-table
()
(let ((table (make-syntax-table)))
(if prolog-underscore-wordchar-flag
(modify-syntax-entry ?_ "w" table)
(modify-syntax-entry ?_ "_" table))
(modify-syntax-entry ?+ "." table)
(modify-syntax-entry ?- "." table)
(modify-syntax-entry ?= "." table)
(modify-syntax-entry ?< "." table)
(modify-syntax-entry ?> "." table)
(modify-syntax-entry ?| "." table)
(modify-syntax-entry ?\' "\"" table)
;; Any better way to handle the 0'<char> construct?!?
(when prolog-char-quote-workaround
(modify-syntax-entry ?0 "\\" table))
(modify-syntax-entry ?% "<" table)
(modify-syntax-entry ?\n ">" table)
(if (eq prolog-emacs 'xemacs)
(progn
(modify-syntax-entry ?* ". 67" table)
(modify-syntax-entry ?/ ". 58" table)
)
;; Emacs wants to see this it seems:
(modify-syntax-entry ?* ". 23b" table)
(modify-syntax-entry ?/ ". 14" table)
)
(setq prolog-mode-syntax-table table)))
(define-abbrev-table 'prolog-mode-abbrev-table ())
(defun prolog-find-value-by-system (alist)
"Get value from ALIST according to `prolog-system'."
(if (listp alist)
(let (result
id)
(while alist
(setq id (car (car alist)))
(if (or (eq id prolog-system)
(eq id t)
(and (listp id)
(eval id)))
(progn
(setq result (car (cdr (car alist))))
(if (and (listp result)
(eq (car result) 'eval))
(setq result (eval (car (cdr result)))))
(setq alist nil))
(setq alist (cdr alist))))
result)
alist))
(defun prolog-mode-variables ()
"Set some common variables to Prolog code specific values."
(setq local-abbrev-table prolog-mode-abbrev-table)
(make-local-variable 'paragraph-start)
(setq paragraph-start (concat "[ \t]*$\\|" page-delimiter)) ;'%%..'
(make-local-variable 'paragraph-separate)
(setq paragraph-separate paragraph-start)
(make-local-variable 'paragraph-ignore-fill-prefix)
(setq paragraph-ignore-fill-prefix t)
(make-local-variable 'adaptive-fill-mode)
(setq adaptive-fill-mode t)
(make-local-variable 'normal-auto-fill-function)
(setq normal-auto-fill-function 'prolog-do-auto-fill)
(make-local-variable 'indent-line-function)
(setq indent-line-function 'prolog-indent-line)
(make-local-variable 'comment-start)
(setq comment-start "%%")
(make-local-variable 'comment-end)
(setq comment-end "")
(make-local-variable 'comment-start-skip)
;; This complex regexp makes sure that comments cannot start
;; inside quoted atoms or strings
(setq comment-start-skip
(format "^\\(\\(%s\\|%s\\|[^\n\'\"%%]\\)*\\)\\(/\\*+ *\\|%%+ *\\)"
prolog-quoted-atom-regexp prolog-string-regexp))
(make-local-variable 'comment-column)
(setq comment-column 0)
(make-local-variable 'comment-indent-function)
(setq comment-indent-function 'prolog-comment-indent)
(make-local-variable 'comment-indent-function)
(setq comment-indent-function 'prolog-comment-indent)
(make-local-variable 'parens-require-spaces)
(setq parens-require-spaces nil)
;; Initialize Prolog system specific variables
(let ((vars '(prolog-keywords prolog-types prolog-mode-specificators
prolog-determinism-specificators prolog-directives
prolog-program-name prolog-program-switches
prolog-consult-string prolog-compile-string prolog-eof-string
prolog-prompt-regexp prolog-continued-prompt-regexp
prolog-help-function)))
(while vars
(set (intern (concat (symbol-name (car vars)) "-i"))
(prolog-find-value-by-system (eval (car vars))))
(setq vars (cdr vars))))
(when (null prolog-program-name-i)
(make-local-variable 'compile-command)
(setq compile-command prolog-compile-string-i))
(make-local-variable 'font-lock-defaults)
(setq font-lock-defaults
'(prolog-font-lock-keywords nil nil ((?_ . "w"))))
)
(defun prolog-mode-keybindings-common (map)
"Define keybindings common to both Prolog modes in MAP."
(define-key map "\C-c?" 'prolog-help-on-predicate)
(define-key map "\C-c/" 'prolog-help-apropos)
(define-key map "\C-c\C-d" 'prolog-debug-on)
(define-key map "\C-c\C-t" 'prolog-trace-on)
(if (and (eq prolog-system 'sicstus)
(prolog-atleast-version '(3 . 7)))
(define-key map "\C-c\C-z" 'prolog-zip-on))
(define-key map "\C-c\r" 'run-prolog))
(defun prolog-mode-keybindings-edit (map)
"Define keybindings for Prolog mode in MAP."
(define-key map "\M-a" 'prolog-beginning-of-clause)
(define-key map "\M-e" 'prolog-end-of-clause)
(define-key map "\M-q" 'prolog-fill-paragraph)
(define-key map "\C-c\C-a" 'align)
(define-key map "\C-\M-a" 'prolog-beginning-of-predicate)
(define-key map "\C-\M-e" 'prolog-end-of-predicate)
(define-key map "\M-\C-c" 'prolog-mark-clause)
(define-key map "\M-\C-h" 'prolog-mark-predicate)
(define-key map "\M-\C-n" 'prolog-forward-list)
(define-key map "\M-\C-p" 'prolog-backward-list)
(define-key map "\C-c\C-n" 'prolog-insert-predicate-template)
(define-key map "\C-c\C-s" 'prolog-insert-predspec)
(define-key map "\M-\r" 'prolog-insert-next-clause)
(define-key map "\C-c\C-va" 'prolog-variables-to-anonymous)
(define-key map "\C-c\C-v\C-s" 'prolog-view-predspec)