prolog.el 128 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422
  1. ;;; prolog.el --- major mode for Prolog (and Mercury) -*- lexical-binding:t -*-
  2. ;; Copyright (C) 1986-1987, 1997-1999, 2002-2003, 2011-2015 Free
  3. ;; Software Foundation, Inc.
  4. ;; Authors: Emil Åström <emil_astrom(at)hotmail(dot)com>
  5. ;; Milan Zamazal <pdm(at)freesoft(dot)cz>
  6. ;; Stefan Bruda <stefan(at)bruda(dot)ca>
  7. ;; * See below for more details
  8. ;; Maintainer: Stefan Bruda <stefan(at)bruda(dot)ca>
  9. ;; Keywords: prolog major mode sicstus swi mercury
  10. (defvar prolog-mode-version "1.22"
  11. "Prolog mode version number.")
  12. ;; This file is part of GNU Emacs.
  13. ;; GNU Emacs is free software: you can redistribute it and/or modify
  14. ;; it under the terms of the GNU General Public License as published by
  15. ;; the Free Software Foundation, either version 3 of the License, or
  16. ;; (at your option) any later version.
  17. ;; GNU Emacs is distributed in the hope that it will be useful,
  18. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. ;; GNU General Public License for more details.
  21. ;; You should have received a copy of the GNU General Public License
  22. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  23. ;; Original author: Masanobu UMEDA <umerin(at)mse(dot)kyutech(dot)ac(dot)jp>
  24. ;; Parts of this file was taken from a modified version of the original
  25. ;; by Johan Andersson, Peter Olin, Mats Carlsson, Johan Bevemyr, Stefan
  26. ;; Andersson, and Per Danielsson (all SICS people), and Henrik Båkman
  27. ;; at Uppsala University, Sweden.
  28. ;;
  29. ;; Some ideas and also a few lines of code have been borrowed (not stolen ;-)
  30. ;; from Oz.el, the Emacs major mode for the Oz programming language,
  31. ;; Copyright (C) 1993 DFKI GmbH, Germany, with permission.
  32. ;; Authored by Ralf Scheidhauer and Michael Mehl
  33. ;; ([scheidhr|mehl](at)dfki(dot)uni-sb(dot)de)
  34. ;;
  35. ;; More ideas and code have been taken from the SICStus debugger mode
  36. ;; (http://www.csd.uu.se/~perm/source_debug/index.shtml -- broken link
  37. ;; as of Mon May 5 08:23:48 EDT 2003) by Per Mildner.
  38. ;;
  39. ;; Additions for ECLiPSe and other helpful suggestions: Stephan Heuel
  40. ;; <heuel(at)ipb(dot)uni-bonn(dot)de>
  41. ;;; Commentary:
  42. ;;
  43. ;; This package provides a major mode for editing Prolog code, with
  44. ;; all the bells and whistles one would expect, including syntax
  45. ;; highlighting and auto indentation. It can also send regions to an
  46. ;; inferior Prolog process.
  47. ;;
  48. ;; The code requires the comint, easymenu, info, imenu, and font-lock
  49. ;; libraries. These are normally distributed with GNU Emacs and
  50. ;; XEmacs.
  51. ;;; Installation:
  52. ;;
  53. ;; Insert the following lines in your init file:
  54. ;;
  55. ;; (setq load-path (cons "/usr/lib/xemacs/site-lisp" load-path))
  56. ;; (autoload 'run-prolog "prolog" "Start a Prolog sub-process." t)
  57. ;; (autoload 'prolog-mode "prolog" "Major mode for editing Prolog programs." t)
  58. ;; (autoload 'mercury-mode "prolog" "Major mode for editing Mercury programs." t)
  59. ;; (setq prolog-system 'swi) ; optional, the system you are using;
  60. ;; ; see `prolog-system' below for possible values
  61. ;; (setq auto-mode-alist (append '(("\\.pl$" . prolog-mode)
  62. ;; ("\\.m$" . mercury-mode))
  63. ;; auto-mode-alist))
  64. ;;
  65. ;; where the path in the first line is the file system path to this file.
  66. ;; MSDOS paths can be written like "d:/programs/emacs-19.34/site-lisp".
  67. ;; Note: In XEmacs, either `/usr/lib/xemacs/site-lisp' (RPM default in
  68. ;; Red Hat-based distributions) or `/usr/local/lib/xemacs/site-lisp'
  69. ;; (default when compiling from sources) are automatically added to
  70. ;; `load-path', so the first line is not necessary provided that you
  71. ;; put this file in the appropriate place.
  72. ;;
  73. ;; The last s-expression above makes sure that files ending with .pl
  74. ;; are assumed to be Prolog files and not Perl, which is the default
  75. ;; Emacs setting. If this is not wanted, remove this line. It is then
  76. ;; necessary to either
  77. ;;
  78. ;; o insert in your Prolog files the following comment as the first line:
  79. ;;
  80. ;; % -*- Mode: Prolog -*-
  81. ;;
  82. ;; and then the file will be open in Prolog mode no matter its
  83. ;; extension, or
  84. ;;
  85. ;; o manually switch to prolog mode after opening a Prolog file, by typing
  86. ;; M-x prolog-mode.
  87. ;;
  88. ;; If the command to start the prolog process ('sicstus', 'pl' or
  89. ;; 'swipl' for SWI prolog, etc.) is not available in the default path,
  90. ;; then it is necessary to set the value of the environment variable
  91. ;; EPROLOG to a shell command to invoke the prolog process. In XEmacs
  92. ;; and Emacs 20+ you can also customize the variable
  93. ;; `prolog-program-name' (in the group `prolog-inferior') and provide
  94. ;; a full path for your Prolog system (swi, scitus, etc.).
  95. ;;
  96. ;; Note: I (Stefan, the current maintainer) work under XEmacs. Future
  97. ;; developments will thus be biased towards XEmacs (OK, I admit it,
  98. ;; I am biased towards XEmacs in general), though I will do my best
  99. ;; to keep the GNU Emacs compatibility. So if you work under Emacs
  100. ;; and see something that does not work do drop me a line, as I have
  101. ;; a smaller chance to notice this kind of bugs otherwise.
  102. ;; Changelog:
  103. ;; Version 1.22:
  104. ;; o Allowed both 'swipl' and 'pl' as names for the SWI Prolog
  105. ;; interpreter.
  106. ;; o Atoms that start a line are not blindly colored as
  107. ;; predicates. Instead we check that they are followed by ( or
  108. ;; :- first. Patch suggested by Guy Wiener.
  109. ;; Version 1.21:
  110. ;; o Cleaned up the code that defines faces. The missing face
  111. ;; warnings on some Emacsen should disappear.
  112. ;; Version 1.20:
  113. ;; o Improved the handling of clause start detection and multi-line
  114. ;; comments: `prolog-clause-start' no longer finds non-predicate
  115. ;; (e.g., capitalized strings) beginning of clauses.
  116. ;; `prolog-tokenize' recognizes when the end point is within a
  117. ;; multi-line comment.
  118. ;; Version 1.19:
  119. ;; o Minimal changes for Aquamacs inclusion and in general for
  120. ;; better coping with finding the Prolog executable. Patch
  121. ;; provided by David Reitter
  122. ;; Version 1.18:
  123. ;; o Fixed syntax highlighting for clause heads that do not begin at
  124. ;; the beginning of the line.
  125. ;; o Fixed compilation warnings under Emacs.
  126. ;; o Updated the email address of the current maintainer.
  127. ;; Version 1.17:
  128. ;; o Minor indentation fix (patch by Markus Triska)
  129. ;; o `prolog-underscore-wordchar-flag' defaults now to nil (more
  130. ;; consistent to other Emacs modes)
  131. ;; Version 1.16:
  132. ;; o Eliminated a possible compilation warning.
  133. ;; Version 1.15:
  134. ;; o Introduced three new customizable variables: electric colon
  135. ;; (`prolog-electric-colon-flag', default nil), electric dash
  136. ;; (`prolog-electric-dash-flag', default nil), and a possibility
  137. ;; to prevent the predicate template insertion from adding commas
  138. ;; (`prolog-electric-dot-full-predicate-template', defaults to t
  139. ;; since it seems quicker to me to just type those commas). A
  140. ;; trivial adaptation of a patch by Markus Triska.
  141. ;; o Improved the behavior of electric if-then-else to only skip
  142. ;; forward if the parenthesis/semicolon is preceded by
  143. ;; whitespace. Once more a trivial adaptation of a patch by
  144. ;; Markus Triska.
  145. ;; Version 1.14:
  146. ;; o Cleaned up align code. `prolog-align-flag' is eliminated (since
  147. ;; on a second thought it does not do anything useful). Added key
  148. ;; binding (C-c C-a) and menu entry for alignment.
  149. ;; o Condensed regular expressions for lower and upper case
  150. ;; characters (GNU Emacs seems to go over the regexp length limit
  151. ;; with the original form). My code on the matter was improved
  152. ;; considerably by Markus Triska.
  153. ;; o Fixed `prolog-insert-spaces-after-paren' (which used an
  154. ;; uninitialized variable).
  155. ;; o Minor changes to clean up the code and avoid some implicit
  156. ;; package requirements.
  157. ;; Version 1.13:
  158. ;; o Removed the use of `map-char-table' in `prolog-build-case-strings'
  159. ;; which appears to cause problems in (at least) Emacs 23.0.0.1.
  160. ;; o Added if-then-else indentation + corresponding electric
  161. ;; characters. New customization: `prolog-electric-if-then-else-flag'
  162. ;; o Align support (requires `align'). New customization:
  163. ;; `prolog-align-flag'.
  164. ;; o Temporary consult files have now the same name throughout the
  165. ;; session. This prevents issues with reconsulting a buffer
  166. ;; (this event is no longer passed to Prolog as a request to
  167. ;; consult a new file).
  168. ;; o Adaptive fill mode is now turned on. Comment indentation is
  169. ;; still worse than it could be though, I am working on it.
  170. ;; o Improved filling and auto-filling capabilities. Now block
  171. ;; comments should be [auto-]filled correctly most of the time;
  172. ;; the following pattern in particular is worth noting as being
  173. ;; filled correctly:
  174. ;; <some code here> % some comment here that goes beyond the
  175. ;; % rightmost column, possibly combined with
  176. ;; % subsequent comment lines
  177. ;; o `prolog-char-quote-workaround' now defaults to nil.
  178. ;; o Note: Many of the above improvements have been suggested by
  179. ;; Markus Triska, who also provided useful patches on the matter
  180. ;; when he realized that I was slow in responding. Many thanks.
  181. ;; Version 1.11 / 1.12
  182. ;; o GNU Emacs compatibility fix for paragraph filling (fixed
  183. ;; incorrectly in 1.11, fix fixed in 1.12).
  184. ;; Version 1.10
  185. ;; o Added paragraph filling in comment blocks and also correct auto
  186. ;; filling for comments.
  187. ;; o Fixed the possible "Regular expression too big" error in
  188. ;; `prolog-electric-dot'.
  189. ;; Version 1.9
  190. ;; o Parenthesis expressions are now indented by default so that
  191. ;; components go one underneath the other, just as for compound
  192. ;; terms. You can use the old style (the second and subsequent
  193. ;; lines being indented to the right in a parenthesis expression)
  194. ;; by setting the customizable variable `prolog-paren-indent-p'
  195. ;; (group "Prolog Indentation") to t.
  196. ;; o (Somehow awkward) handling of the 0' character escape
  197. ;; sequence. I am looking into a better way of doing it but
  198. ;; prospects look bleak. If this breaks things for you please let
  199. ;; me know and also set the `prolog-char-quote-workaround' (group
  200. ;; "Prolog Other") to nil.
  201. ;; Version 1.8
  202. ;; o Key binding fix.
  203. ;; Version 1.7
  204. ;; o Fixed a number of issues with the syntax of single quotes,
  205. ;; including Debian bug #324520.
  206. ;; Version 1.6
  207. ;; o Fixed mercury mode menu initialization (Debian bug #226121).
  208. ;; o Fixed (i.e., eliminated) Delete remapping (Debian bug #229636).
  209. ;; o Corrected indentation for clauses defining quoted atoms.
  210. ;; Version 1.5:
  211. ;; o Keywords fontifying should work in console mode so this is
  212. ;; enabled everywhere.
  213. ;; Version 1.4:
  214. ;; o Now supports GNU Prolog--minor adaptation of a patch by Stefan
  215. ;; Moeding.
  216. ;; Version 1.3:
  217. ;; o Info-follow-nearest-node now called correctly under Emacs too
  218. ;; (thanks to Nicolas Pelletier). Should be implemented more
  219. ;; elegantly (i.e., without compilation warnings) in the future.
  220. ;; Version 1.2:
  221. ;; o Another prompt fix, still in SWI mode (people seem to have
  222. ;; changed the prompt of SWI Prolog).
  223. ;; Version 1.1:
  224. ;; o Fixed dots in the end of line comments causing indentation
  225. ;; problems. The following code is now correctly indented (note
  226. ;; the dot terminating the comment):
  227. ;; a(X) :- b(X),
  228. ;; c(X). % comment here.
  229. ;; a(X).
  230. ;; and so is this (and variants):
  231. ;; a(X) :- b(X),
  232. ;; c(X). /* comment here. */
  233. ;; a(X).
  234. ;; Version 1.0:
  235. ;; o Revamped the menu system.
  236. ;; o Yet another prompt recognition fix (SWI mode).
  237. ;; o This is more of a renumbering than a new edition. I promoted
  238. ;; the mode to version 1.0 to emphasize the fact that it is now
  239. ;; mature and stable enough to be considered production (in my
  240. ;; opinion anyway).
  241. ;; Version 0.1.41:
  242. ;; o GNU Emacs compatibility fixes.
  243. ;; Version 0.1.40:
  244. ;; o prolog-get-predspec is now suitable to be called as
  245. ;; imenu-extract-index-name-function. The predicate index works.
  246. ;; o Since imenu works now as advertised, prolog-imenu-flag is t
  247. ;; by default.
  248. ;; o Eliminated prolog-create-predicate-index since the imenu
  249. ;; utilities now work well. Actually, this function is also
  250. ;; buggy, and I see no reason to fix it since we do not need it
  251. ;; anyway.
  252. ;; o Fixed prolog-pred-start, prolog-clause-start, prolog-clause-info.
  253. ;; o Fix for prolog-build-case-strings; now prolog-upper-case-string
  254. ;; and prolog-lower-case-string are correctly initialized,
  255. ;; o Various font-lock changes; most importantly, block comments (/*
  256. ;; ... */) are now correctly fontified in XEmacs even when they
  257. ;; extend on multiple lines.
  258. ;; Version 0.1.36:
  259. ;; o The debug prompt of SWI Prolog is now correctly recognized.
  260. ;; Version 0.1.35:
  261. ;; o Minor font-lock bug fixes.
  262. ;;; TODO:
  263. ;; Replace ":type 'sexp" with more precise Custom types.
  264. ;;; Code:
  265. (require 'comint)
  266. (eval-when-compile
  267. (require 'font-lock)
  268. ;; We need imenu everywhere because of the predicate index!
  269. (require 'imenu)
  270. ;)
  271. (require 'shell)
  272. )
  273. (require 'easymenu)
  274. (require 'align)
  275. (defgroup prolog nil
  276. "Editing and running Prolog and Mercury files."
  277. :group 'languages)
  278. (defgroup prolog-faces nil
  279. "Prolog mode specific faces."
  280. :group 'font-lock)
  281. (defgroup prolog-indentation nil
  282. "Prolog mode indentation configuration."
  283. :group 'prolog)
  284. (defgroup prolog-font-lock nil
  285. "Prolog mode font locking patterns."
  286. :group 'prolog)
  287. (defgroup prolog-keyboard nil
  288. "Prolog mode keyboard flags."
  289. :group 'prolog)
  290. (defgroup prolog-inferior nil
  291. "Inferior Prolog mode options."
  292. :group 'prolog)
  293. (defgroup prolog-other nil
  294. "Other Prolog mode options."
  295. :group 'prolog)
  296. ;;-------------------------------------------------------------------
  297. ;; User configurable variables
  298. ;;-------------------------------------------------------------------
  299. ;; General configuration
  300. (defcustom prolog-system nil
  301. "Prolog interpreter/compiler used.
  302. The value of this variable is nil or a symbol.
  303. If it is a symbol, it determines default values of other configuration
  304. variables with respect to properties of the specified Prolog
  305. interpreter/compiler.
  306. Currently recognized symbol values are:
  307. eclipse - Eclipse Prolog
  308. mercury - Mercury
  309. sicstus - SICStus Prolog
  310. swi - SWI Prolog
  311. gnu - GNU Prolog"
  312. :version "24.1"
  313. :group 'prolog
  314. :type '(choice (const :tag "SICStus" :value sicstus)
  315. (const :tag "SWI Prolog" :value swi)
  316. (const :tag "GNU Prolog" :value gnu)
  317. (const :tag "ECLiPSe Prolog" :value eclipse)
  318. ;; Mercury shouldn't be needed since we have a separate
  319. ;; major mode for it.
  320. (const :tag "Default" :value nil)))
  321. (make-variable-buffer-local 'prolog-system)
  322. ;; NB: This alist can not be processed in prolog-mode-variables to
  323. ;; create a prolog-system-version-i variable since it is needed
  324. ;; prior to the call to prolog-mode-variables.
  325. (defcustom prolog-system-version
  326. '((sicstus (3 . 6))
  327. (swi (0 . 0))
  328. (mercury (0 . 0))
  329. (eclipse (3 . 7))
  330. (gnu (0 . 0)))
  331. ;; FIXME: This should be auto-detected instead of user-provided.
  332. "Alist of Prolog system versions.
  333. The version numbers are of the format (Major . Minor)."
  334. :version "24.1"
  335. :type '(repeat (list (symbol :tag "System")
  336. (cons :tag "Version numbers" (integer :tag "Major")
  337. (integer :tag "Minor"))))
  338. :group 'prolog)
  339. ;; Indentation
  340. (defcustom prolog-indent-width 4
  341. "The indentation width used by the editing buffer."
  342. :group 'prolog-indentation
  343. :type 'integer)
  344. (defcustom prolog-left-indent-regexp "\\(;\\|\\*?->\\)"
  345. "Regexp for `prolog-electric-if-then-else-flag'."
  346. :version "24.1"
  347. :group 'prolog-indentation
  348. :type 'regexp)
  349. (defcustom prolog-paren-indent-p nil
  350. "If non-nil, increase indentation for parenthesis expressions.
  351. The second and subsequent line in a parenthesis expression other than
  352. a compound term can either be indented `prolog-paren-indent' to the
  353. right (if this variable is non-nil) or in the same way as for compound
  354. terms (if this variable is nil, default)."
  355. :version "24.1"
  356. :group 'prolog-indentation
  357. :type 'boolean)
  358. (defcustom prolog-paren-indent 4
  359. "The indentation increase for parenthesis expressions.
  360. Only used in ( If -> Then ; Else) and ( Disj1 ; Disj2 ) style expressions."
  361. :version "24.1"
  362. :group 'prolog-indentation
  363. :type 'integer)
  364. (defcustom prolog-parse-mode 'beg-of-clause
  365. "The parse mode used (decides from which point parsing is done).
  366. Legal values:
  367. 'beg-of-line - starts parsing at the beginning of a line, unless the
  368. previous line ends with a backslash. Fast, but has
  369. problems detecting multiline /* */ comments.
  370. 'beg-of-clause - starts parsing at the beginning of the current clause.
  371. Slow, but copes better with /* */ comments."
  372. :version "24.1"
  373. :group 'prolog-indentation
  374. :type '(choice (const :value beg-of-line)
  375. (const :value beg-of-clause)))
  376. ;; Font locking
  377. (defcustom prolog-keywords
  378. '((eclipse
  379. ("use_module" "begin_module" "module_interface" "dynamic"
  380. "external" "export" "dbgcomp" "nodbgcomp" "compile"))
  381. (mercury
  382. ("all" "else" "end_module" "equality" "external" "fail" "func" "if"
  383. "implementation" "import_module" "include_module" "inst" "instance"
  384. "interface" "mode" "module" "not" "pragma" "pred" "some" "then" "true"
  385. "type" "typeclass" "use_module" "where"))
  386. (sicstus
  387. ("block" "dynamic" "mode" "module" "multifile" "meta_predicate"
  388. "parallel" "public" "sequential" "volatile"))
  389. (swi
  390. ("discontiguous" "dynamic" "ensure_loaded" "export" "export_list" "import"
  391. "meta_predicate" "module" "module_transparent" "multifile" "require"
  392. "use_module" "volatile"))
  393. (gnu
  394. ("built_in" "char_conversion" "discontiguous" "dynamic" "ensure_linked"
  395. "ensure_loaded" "foreign" "include" "initialization" "multifile" "op"
  396. "public" "set_prolog_flag"))
  397. (t
  398. ;; FIXME: Shouldn't we just use the union of all the above here?
  399. ("dynamic" "module")))
  400. "Alist of Prolog keywords which is used for font locking of directives."
  401. :version "24.1"
  402. :group 'prolog-font-lock
  403. :type 'sexp)
  404. (defcustom prolog-types
  405. '((mercury
  406. ("char" "float" "int" "io__state" "string" "univ"))
  407. (t nil))
  408. "Alist of Prolog types used by font locking."
  409. :version "24.1"
  410. :group 'prolog-font-lock
  411. :type 'sexp)
  412. (defcustom prolog-mode-specificators
  413. '((mercury
  414. ("bound" "di" "free" "ground" "in" "mdi" "mui" "muo" "out" "ui" "uo"))
  415. (t nil))
  416. "Alist of Prolog mode specificators used by font locking."
  417. :version "24.1"
  418. :group 'prolog-font-lock
  419. :type 'sexp)
  420. (defcustom prolog-determinism-specificators
  421. '((mercury
  422. ("cc_multi" "cc_nondet" "det" "erroneous" "failure" "multi" "nondet"
  423. "semidet"))
  424. (t nil))
  425. "Alist of Prolog determinism specificators used by font locking."
  426. :version "24.1"
  427. :group 'prolog-font-lock
  428. :type 'sexp)
  429. (defcustom prolog-directives
  430. '((mercury
  431. ("^#[0-9]+"))
  432. (t nil))
  433. "Alist of Prolog source code directives used by font locking."
  434. :version "24.1"
  435. :group 'prolog-font-lock
  436. :type 'sexp)
  437. ;; Keyboard
  438. (defcustom prolog-hungry-delete-key-flag nil
  439. "Non-nil means delete key consumes all preceding spaces."
  440. :version "24.1"
  441. :group 'prolog-keyboard
  442. :type 'boolean)
  443. (defcustom prolog-electric-dot-flag nil
  444. "Non-nil means make dot key electric.
  445. Electric dot appends newline or inserts head of a new clause.
  446. If dot is pressed at the end of a line where at least one white space
  447. precedes the point, it inserts a recursive call to the current predicate.
  448. If dot is pressed at the beginning of an empty line, it inserts the head
  449. of a new clause for the current predicate. It does not apply in strings
  450. and comments.
  451. It does not apply in strings and comments."
  452. :version "24.1"
  453. :group 'prolog-keyboard
  454. :type 'boolean)
  455. (defcustom prolog-electric-dot-full-predicate-template nil
  456. "If nil, electric dot inserts only the current predicate's name and `('
  457. for recursive calls or new clause heads. Non-nil means to also
  458. insert enough commas to cover the predicate's arity and `)',
  459. and dot and newline for recursive calls."
  460. :version "24.1"
  461. :group 'prolog-keyboard
  462. :type 'boolean)
  463. (defcustom prolog-electric-underscore-flag nil
  464. "Non-nil means make underscore key electric.
  465. Electric underscore replaces the current variable with underscore.
  466. If underscore is pressed not on a variable then it behaves as usual."
  467. :version "24.1"
  468. :group 'prolog-keyboard
  469. :type 'boolean)
  470. (defcustom prolog-electric-if-then-else-flag nil
  471. "Non-nil makes `(', `>' and `;' electric
  472. to automatically indent if-then-else constructs."
  473. :version "24.1"
  474. :group 'prolog-keyboard
  475. :type 'boolean)
  476. (defcustom prolog-electric-colon-flag nil
  477. "Makes `:' electric (inserts `:-' on a new line).
  478. If non-nil, pressing `:' at the end of a line that starts in
  479. the first column (i.e., clause heads) inserts ` :-' and newline."
  480. :version "24.1"
  481. :group 'prolog-keyboard
  482. :type 'boolean)
  483. (defcustom prolog-electric-dash-flag nil
  484. "Makes `-' electric (inserts a `-->' on a new line).
  485. If non-nil, pressing `-' at the end of a line that starts in
  486. the first column (i.e., DCG heads) inserts ` -->' and newline."
  487. :version "24.1"
  488. :group 'prolog-keyboard
  489. :type 'boolean)
  490. (defcustom prolog-old-sicstus-keys-flag nil
  491. "Non-nil means old SICStus Prolog mode keybindings are used."
  492. :version "24.1"
  493. :group 'prolog-keyboard
  494. :type 'boolean)
  495. ;; Inferior mode
  496. (defcustom prolog-program-name
  497. `(((getenv "EPROLOG") (eval (getenv "EPROLOG")))
  498. (eclipse "eclipse")
  499. (mercury nil)
  500. (sicstus "sicstus")
  501. (swi ,(if (not (executable-find "swipl")) "pl" "swipl"))
  502. (gnu "gprolog")
  503. (t ,(let ((names '("prolog" "gprolog" "swipl" "pl")))
  504. (while (and names
  505. (not (executable-find (car names))))
  506. (setq names (cdr names)))
  507. (or (car names) "prolog"))))
  508. "Alist of program names for invoking an inferior Prolog with `run-prolog'."
  509. :group 'prolog-inferior
  510. :type 'sexp)
  511. (defun prolog-program-name ()
  512. (prolog-find-value-by-system prolog-program-name))
  513. (defcustom prolog-program-switches
  514. '((sicstus ("-i"))
  515. (t nil))
  516. "Alist of switches given to inferior Prolog run with `run-prolog'."
  517. :version "24.1"
  518. :group 'prolog-inferior
  519. :type 'sexp)
  520. (defun prolog-program-switches ()
  521. (prolog-find-value-by-system prolog-program-switches))
  522. (defcustom prolog-consult-string
  523. '((eclipse "[%f].")
  524. (mercury nil)
  525. (sicstus (eval (if (prolog-atleast-version '(3 . 7))
  526. "prolog:zap_file(%m,%b,consult,%l)."
  527. "prolog:zap_file(%m,%b,consult).")))
  528. (swi "[%f].")
  529. (gnu "[%f].")
  530. (t "reconsult(%f)."))
  531. "Alist of strings defining predicate for reconsulting.
  532. Some parts of the string are replaced:
  533. `%f' by the name of the consulted file (can be a temporary file)
  534. `%b' by the file name of the buffer to consult
  535. `%m' by the module name and name of the consulted file separated by colon
  536. `%l' by the line offset into the file. This is 0 unless consulting a
  537. region of a buffer, in which case it is the number of lines before
  538. the region."
  539. :group 'prolog-inferior
  540. :type 'sexp)
  541. (defun prolog-consult-string ()
  542. (prolog-find-value-by-system prolog-consult-string))
  543. (defcustom prolog-compile-string
  544. '((eclipse "[%f].")
  545. (mercury "mmake ")
  546. (sicstus (eval (if (prolog-atleast-version '(3 . 7))
  547. "prolog:zap_file(%m,%b,compile,%l)."
  548. "prolog:zap_file(%m,%b,compile).")))
  549. (swi "[%f].")
  550. (t "compile(%f)."))
  551. "Alist of strings and lists defining predicate for recompilation.
  552. Some parts of the string are replaced:
  553. `%f' by the name of the compiled file (can be a temporary file)
  554. `%b' by the file name of the buffer to compile
  555. `%m' by the module name and name of the compiled file separated by colon
  556. `%l' by the line offset into the file. This is 0 unless compiling a
  557. region of a buffer, in which case it is the number of lines before
  558. the region.
  559. If `prolog-program-name' is non-nil, it is a string sent to a Prolog process.
  560. If `prolog-program-name' is nil, it is an argument to the `compile' function."
  561. :group 'prolog-inferior
  562. :type 'sexp)
  563. (defun prolog-compile-string ()
  564. (prolog-find-value-by-system prolog-compile-string))
  565. (defcustom prolog-eof-string "end_of_file.\n"
  566. "Alist of strings that represent end of file for prolog.
  567. nil means send actual operating system end of file."
  568. :group 'prolog-inferior
  569. :type 'sexp)
  570. (defcustom prolog-prompt-regexp
  571. '((eclipse "^[a-zA-Z0-9()]* *\\?- \\|^\\[[a-zA-Z]* [0-9]*\\]:")
  572. (sicstus "| [ ?][- ] *")
  573. (swi "^\\(\\[[a-zA-Z]*\\] \\)?[1-9]?[0-9]*[ ]?\\?- \\|^| +")
  574. (gnu "^| \\?-")
  575. (t "^|? *\\?-"))
  576. "Alist of prompts of the prolog system command line."
  577. :version "24.1"
  578. :group 'prolog-inferior
  579. :type 'sexp)
  580. (defun prolog-prompt-regexp ()
  581. (prolog-find-value-by-system prolog-prompt-regexp))
  582. ;; (defcustom prolog-continued-prompt-regexp
  583. ;; '((sicstus "^\\(| +\\| +\\)")
  584. ;; (t "^|: +"))
  585. ;; "Alist of regexps matching the prompt when consulting `user'."
  586. ;; :group 'prolog-inferior
  587. ;; :type 'sexp)
  588. (defcustom prolog-debug-on-string "debug.\n"
  589. "Predicate for enabling debug mode."
  590. :version "24.1"
  591. :group 'prolog-inferior
  592. :type 'string)
  593. (defcustom prolog-debug-off-string "nodebug.\n"
  594. "Predicate for disabling debug mode."
  595. :version "24.1"
  596. :group 'prolog-inferior
  597. :type 'string)
  598. (defcustom prolog-trace-on-string "trace.\n"
  599. "Predicate for enabling tracing."
  600. :version "24.1"
  601. :group 'prolog-inferior
  602. :type 'string)
  603. (defcustom prolog-trace-off-string "notrace.\n"
  604. "Predicate for disabling tracing."
  605. :version "24.1"
  606. :group 'prolog-inferior
  607. :type 'string)
  608. (defcustom prolog-zip-on-string "zip.\n"
  609. "Predicate for enabling zip mode for SICStus."
  610. :version "24.1"
  611. :group 'prolog-inferior
  612. :type 'string)
  613. (defcustom prolog-zip-off-string "nozip.\n"
  614. "Predicate for disabling zip mode for SICStus."
  615. :version "24.1"
  616. :group 'prolog-inferior
  617. :type 'string)
  618. (defcustom prolog-use-standard-consult-compile-method-flag t
  619. "Non-nil means use the standard compilation method.
  620. Otherwise the new compilation method will be used. This
  621. utilizes a special compilation buffer with the associated
  622. features such as parsing of error messages and automatically
  623. jumping to the source code responsible for the error.
  624. Warning: the new method is so far only experimental and
  625. does contain bugs. The recommended setting for the novice user
  626. is non-nil for this variable."
  627. :version "24.1"
  628. :group 'prolog-inferior
  629. :type 'boolean)
  630. ;; Miscellaneous
  631. (defcustom prolog-imenu-flag t
  632. "Non-nil means add a clause index menu for all prolog files."
  633. :version "24.1"
  634. :group 'prolog-other
  635. :type 'boolean)
  636. (defcustom prolog-imenu-max-lines 3000
  637. "The maximum number of lines of the file for imenu to be enabled.
  638. Relevant only when `prolog-imenu-flag' is non-nil."
  639. :version "24.1"
  640. :group 'prolog-other
  641. :type 'integer)
  642. (defcustom prolog-info-predicate-index
  643. "(sicstus)Predicate Index"
  644. "The info node for the SICStus predicate index."
  645. :version "24.1"
  646. :group 'prolog-other
  647. :type 'string)
  648. (defcustom prolog-underscore-wordchar-flag nil
  649. "Non-nil means underscore (_) is a word-constituent character."
  650. :version "24.1"
  651. :group 'prolog-other
  652. :type 'boolean)
  653. (make-obsolete-variable 'prolog-underscore-wordchar-flag
  654. 'superword-mode "24.4")
  655. (defcustom prolog-use-sicstus-sd nil
  656. "If non-nil, use the source level debugger of SICStus 3#7 and later."
  657. :version "24.1"
  658. :group 'prolog-other
  659. :type 'boolean)
  660. (defcustom prolog-char-quote-workaround nil
  661. "If non-nil, declare 0 as a quote character to handle 0'<char>.
  662. This is really kludgy, and unneeded (i.e. obsolete) in Emacs>=24."
  663. :version "24.1"
  664. :group 'prolog-other
  665. :type 'boolean)
  666. (make-obsolete-variable 'prolog-char-quote-workaround nil "24.1")
  667. ;;-------------------------------------------------------------------
  668. ;; Internal variables
  669. ;;-------------------------------------------------------------------
  670. ;;(defvar prolog-temp-filename "") ; Later set by `prolog-temporary-file'
  671. (defvar prolog-mode-syntax-table
  672. ;; The syntax accepted varies depending on the implementation used.
  673. ;; Here are some of the differences:
  674. ;; - SWI-Prolog accepts nested /*..*/ comments.
  675. ;; - Edinburgh-style Prologs take <radix>'<number> for non-decimal number,
  676. ;; whereas ISO-style Prologs use 0[obx]<number> instead.
  677. ;; - In atoms \x<hex> sometimes needs a terminating \ (ISO-style)
  678. ;; and sometimes not.
  679. (let ((table (make-syntax-table)))
  680. (modify-syntax-entry ?_ (if prolog-underscore-wordchar-flag "w" "_") table)
  681. (modify-syntax-entry ?+ "." table)
  682. (modify-syntax-entry ?- "." table)
  683. (modify-syntax-entry ?= "." table)
  684. (modify-syntax-entry ?< "." table)
  685. (modify-syntax-entry ?> "." table)
  686. (modify-syntax-entry ?| "." table)
  687. (modify-syntax-entry ?\' "\"" table)
  688. ;; Any better way to handle the 0'<char> construct?!?
  689. (when (and prolog-char-quote-workaround
  690. (not (fboundp 'syntax-propertize-rules)))
  691. (modify-syntax-entry ?0 "\\" table))
  692. (modify-syntax-entry ?% "<" table)
  693. (modify-syntax-entry ?\n ">" table)
  694. (if (featurep 'xemacs)
  695. (progn
  696. (modify-syntax-entry ?* ". 67" table)
  697. (modify-syntax-entry ?/ ". 58" table)
  698. )
  699. ;; Emacs wants to see this it seems:
  700. (modify-syntax-entry ?* ". 23b" table)
  701. (modify-syntax-entry ?/ ". 14" table)
  702. )
  703. table))
  704. (defconst prolog-atom-char-regexp
  705. "[[:alnum:]_$]"
  706. "Regexp specifying characters which constitute atoms without quoting.")
  707. (defconst prolog-atom-regexp
  708. (format "[[:lower:]$]%s*" prolog-atom-char-regexp))
  709. (defconst prolog-left-paren "[[({]" ;FIXME: Why not \\s(?
  710. "The characters used as left parentheses for the indentation code.")
  711. (defconst prolog-right-paren "[])}]" ;FIXME: Why not \\s)?
  712. "The characters used as right parentheses for the indentation code.")
  713. (defconst prolog-quoted-atom-regexp
  714. "\\(^\\|[^0-9]\\)\\('\\([^\n']\\|\\\\'\\)*'\\)"
  715. "Regexp matching a quoted atom.")
  716. (defconst prolog-string-regexp
  717. "\\(\"\\([^\n\"]\\|\\\\\"\\)*\"\\)"
  718. "Regexp matching a string.")
  719. (defconst prolog-head-delimiter "\\(:-\\|\\+:\\|-:\\|\\+\\?\\|-\\?\\|-->\\)"
  720. "A regexp for matching on the end delimiter of a head (e.g. \":-\").")
  721. (defvar prolog-compilation-buffer "*prolog-compilation*"
  722. "Name of the output buffer for Prolog compilation/consulting.")
  723. (defvar prolog-temporary-file-name nil)
  724. (defvar prolog-keywords-i nil)
  725. (defvar prolog-types-i nil)
  726. (defvar prolog-mode-specificators-i nil)
  727. (defvar prolog-determinism-specificators-i nil)
  728. (defvar prolog-directives-i nil)
  729. (defvar prolog-eof-string-i nil)
  730. ;; (defvar prolog-continued-prompt-regexp-i nil)
  731. (defvar prolog-help-function-i nil)
  732. (defvar prolog-align-rules
  733. (eval-when-compile
  734. (mapcar
  735. (lambda (x)
  736. (let ((name (car x))
  737. (sym (cdr x)))
  738. `(,(intern (format "prolog-%s" name))
  739. (regexp . ,(format "\\(\\s-*\\)%s\\(\\s-*\\)" sym))
  740. (tab-stop . nil)
  741. (modes . '(prolog-mode))
  742. (group . (1 2)))))
  743. '(("dcg" . "-->") ("rule" . ":-") ("simplification" . "<=>")
  744. ("propagation" . "==>")))))
  745. ;; SMIE support
  746. (require 'smie)
  747. (defun prolog-smie-forward-token ()
  748. ;; FIXME: Add support for 0'<char>, if needed after adding it to
  749. ;; syntax-propertize-functions.
  750. (forward-comment (point-max))
  751. (buffer-substring-no-properties
  752. (point)
  753. (progn (cond
  754. ((looking-at "[!;]") (forward-char 1))
  755. ((not (zerop (skip-chars-forward "#&*+-./:<=>?@\\^`~"))))
  756. ((not (zerop (skip-syntax-forward "w_'"))))
  757. ;; In case of non-ASCII punctuation.
  758. ((not (zerop (skip-syntax-forward ".")))))
  759. (point))))
  760. (defun prolog-smie-backward-token ()
  761. ;; FIXME: Add support for 0'<char>, if needed after adding it to
  762. ;; syntax-propertize-functions.
  763. (forward-comment (- (point-max)))
  764. (buffer-substring-no-properties
  765. (point)
  766. (progn (cond
  767. ((memq (char-before) '(?! ?\;)) (forward-char -1))
  768. ((not (zerop (skip-chars-backward "#&*+-./:<=>?@\\^`~"))))
  769. ((not (zerop (skip-syntax-backward "w_'"))))
  770. ;; In case of non-ASCII punctuation.
  771. ((not (zerop (skip-syntax-backward ".")))))
  772. (point))))
  773. (defconst prolog-smie-grammar
  774. ;; Rather than construct the operator levels table from the BNF,
  775. ;; we directly provide the operator precedences from GNU Prolog's
  776. ;; manual (7.14.10 op/3). The only problem is that GNU Prolog's
  777. ;; manual uses precedence levels in the opposite sense (higher
  778. ;; numbers bind less tightly) than SMIE, so we use negative numbers.
  779. '(("." -10000 -10000)
  780. (":-" -1200 -1200)
  781. ("-->" -1200 -1200)
  782. (";" -1100 -1100)
  783. ("->" -1050 -1050)
  784. ("," -1000 -1000)
  785. ("\\+" -900 -900)
  786. ("=" -700 -700)
  787. ("\\=" -700 -700)
  788. ("=.." -700 -700)
  789. ("==" -700 -700)
  790. ("\\==" -700 -700)
  791. ("@<" -700 -700)
  792. ("@=<" -700 -700)
  793. ("@>" -700 -700)
  794. ("@>=" -700 -700)
  795. ("is" -700 -700)
  796. ("=:=" -700 -700)
  797. ("=\\=" -700 -700)
  798. ("<" -700 -700)
  799. ("=<" -700 -700)
  800. (">" -700 -700)
  801. (">=" -700 -700)
  802. (":" -600 -600)
  803. ("+" -500 -500)
  804. ("-" -500 -500)
  805. ("/\\" -500 -500)
  806. ("\\/" -500 -500)
  807. ("*" -400 -400)
  808. ("/" -400 -400)
  809. ("//" -400 -400)
  810. ("rem" -400 -400)
  811. ("mod" -400 -400)
  812. ("<<" -400 -400)
  813. (">>" -400 -400)
  814. ("**" -200 -200)
  815. ("^" -200 -200)
  816. ;; Prefix
  817. ;; ("+" 200 200)
  818. ;; ("-" 200 200)
  819. ;; ("\\" 200 200)
  820. (:smie-closer-alist (t . "."))
  821. )
  822. "Precedence levels of infix operators.")
  823. (defun prolog-smie-rules (kind token)
  824. (pcase (cons kind token)
  825. (`(:elem . basic) prolog-indent-width)
  826. (`(:after . ".") '(column . 0)) ;; To work around smie-closer-alist.
  827. ;; Allow indentation of if-then-else as:
  828. ;; ( test
  829. ;; -> thenrule
  830. ;; ; elserule
  831. ;; )
  832. (`(:before . ,(or `"->" `";"))
  833. (and (smie-rule-bolp) (smie-rule-parent-p "(") (smie-rule-parent 1)))
  834. (`(:after . ,(or `":-" `"->" `"-->")) prolog-indent-width)))
  835. ;;-------------------------------------------------------------------
  836. ;; Prolog mode
  837. ;;-------------------------------------------------------------------
  838. ;; Example: (prolog-atleast-version '(3 . 6))
  839. (defun prolog-atleast-version (version)
  840. "Return t if the version of the current prolog system is VERSION or later.
  841. VERSION is of the format (Major . Minor)"
  842. ;; Version.major < major or
  843. ;; Version.major = major and Version.minor <= minor
  844. (let* ((thisversion (prolog-find-value-by-system prolog-system-version))
  845. (thismajor (car thisversion))
  846. (thisminor (cdr thisversion)))
  847. (or (< (car version) thismajor)
  848. (and (= (car version) thismajor)
  849. (<= (cdr version) thisminor)))
  850. ))
  851. (define-abbrev-table 'prolog-mode-abbrev-table ())
  852. (defun prolog-find-value-by-system (alist)
  853. "Get value from ALIST according to `prolog-system'."
  854. (let ((system (or prolog-system
  855. (let ((infbuf (prolog-inferior-buffer 'dont-run)))
  856. (when infbuf
  857. (buffer-local-value 'prolog-system infbuf))))))
  858. (if (listp alist)
  859. (let (result
  860. id)
  861. (while alist
  862. (setq id (car (car alist)))
  863. (if (or (eq id system)
  864. (eq id t)
  865. (and (listp id)
  866. (eval id)))
  867. (progn
  868. (setq result (car (cdr (car alist))))
  869. (if (and (listp result)
  870. (eq (car result) 'eval))
  871. (setq result (eval (car (cdr result)))))
  872. (setq alist nil))
  873. (setq alist (cdr alist))))
  874. result)
  875. alist)))
  876. (defconst prolog-syntax-propertize-function
  877. (when (fboundp 'syntax-propertize-rules)
  878. (syntax-propertize-rules
  879. ;; GNU Prolog only accepts 0'\' rather than 0'', but the only
  880. ;; possible meaning of 0'' is rather clear.
  881. ("\\<0\\(''?\\)"
  882. (1 (unless (save-excursion (nth 8 (syntax-ppss (match-beginning 0))))
  883. (string-to-syntax "_"))))
  884. ;; We could check that we're not inside an atom, but I don't think
  885. ;; that 'foo 8'z could be a valid syntax anyway, so why bother?
  886. ("\\<[1-9][0-9]*\\('\\)[0-9a-zA-Z]" (1 "_"))
  887. ;; Supposedly, ISO-Prolog wants \NNN\ for octal and \xNNN\ for hexadecimal
  888. ;; escape sequences in atoms, so be careful not to let the terminating \
  889. ;; escape a subsequent quote.
  890. ("\\\\[x0-7][0-9a-fA-F]*\\(\\\\\\)" (1 "_"))
  891. )))
  892. (defun prolog-mode-variables ()
  893. "Set some common variables to Prolog code specific values."
  894. (setq-local local-abbrev-table prolog-mode-abbrev-table)
  895. (setq-local paragraph-start (concat "[ \t]*$\\|" page-delimiter)) ;'%%..'
  896. (setq-local paragraph-separate paragraph-start)
  897. (setq-local paragraph-ignore-fill-prefix t)
  898. (setq-local normal-auto-fill-function 'prolog-do-auto-fill)
  899. (setq-local comment-start "%")
  900. (setq-local comment-end "")
  901. (setq-local comment-add 1)
  902. (setq-local comment-start-skip "\\(?:/\\*+ *\\|%%+ *\\)")
  903. (setq-local parens-require-spaces nil)
  904. ;; Initialize Prolog system specific variables
  905. (dolist (var '(prolog-keywords prolog-types prolog-mode-specificators
  906. prolog-determinism-specificators prolog-directives
  907. prolog-eof-string
  908. ;; prolog-continued-prompt-regexp
  909. prolog-help-function))
  910. (set (intern (concat (symbol-name var) "-i"))
  911. (prolog-find-value-by-system (symbol-value var))))
  912. (when (null (prolog-program-name))
  913. (setq-local compile-command (prolog-compile-string)))
  914. (setq-local font-lock-defaults
  915. '(prolog-font-lock-keywords nil nil ((?_ . "w"))))
  916. (setq-local syntax-propertize-function prolog-syntax-propertize-function)
  917. (smie-setup prolog-smie-grammar #'prolog-smie-rules
  918. :forward-token #'prolog-smie-forward-token
  919. :backward-token #'prolog-smie-backward-token))
  920. (defun prolog-mode-keybindings-common (map)
  921. "Define keybindings common to both Prolog modes in MAP."
  922. (define-key map "\C-c?" 'prolog-help-on-predicate)
  923. (define-key map "\C-c/" 'prolog-help-apropos)
  924. (define-key map "\C-c\C-d" 'prolog-debug-on)
  925. (define-key map "\C-c\C-t" 'prolog-trace-on)
  926. (define-key map "\C-c\C-z" 'prolog-zip-on)
  927. (define-key map "\C-c\r" 'run-prolog))
  928. (defun prolog-mode-keybindings-edit (map)
  929. "Define keybindings for Prolog mode in MAP."
  930. (define-key map "\M-a" 'prolog-beginning-of-clause)
  931. (define-key map "\M-e" 'prolog-end-of-clause)
  932. (define-key map "\M-q" 'prolog-fill-paragraph)
  933. (define-key map "\C-c\C-a" 'align)
  934. (define-key map "\C-\M-a" 'prolog-beginning-of-predicate)
  935. (define-key map "\C-\M-e" 'prolog-end-of-predicate)
  936. (define-key map "\M-\C-c" 'prolog-mark-clause)
  937. (define-key map "\M-\C-h" 'prolog-mark-predicate)
  938. (define-key map "\C-c\C-n" 'prolog-insert-predicate-template)
  939. (define-key map "\C-c\C-s" 'prolog-insert-predspec)
  940. (define-key map "\M-\r" 'prolog-insert-next-clause)
  941. (define-key map "\C-c\C-va" 'prolog-variables-to-anonymous)
  942. (define-key map "\C-c\C-v\C-s" 'prolog-view-predspec)
  943. ;; If we're running SICStus, then map C-c C-c e/d to enabling
  944. ;; and disabling of the source-level debugging facilities.
  945. ;(if (and (eq prolog-system 'sicstus)
  946. ; (prolog-atleast-version '(3 . 7)))
  947. ; (progn
  948. ; (define-key map "\C-c\C-ce" 'prolog-enable-sicstus-sd)
  949. ; (define-key map "\C-c\C-cd" 'prolog-disable-sicstus-sd)
  950. ; ))
  951. (if prolog-old-sicstus-keys-flag
  952. (progn
  953. (define-key map "\C-c\C-c" 'prolog-consult-predicate)
  954. (define-key map "\C-cc" 'prolog-consult-region)
  955. (define-key map "\C-cC" 'prolog-consult-buffer)
  956. (define-key map "\C-c\C-k" 'prolog-compile-predicate)
  957. (define-key map "\C-ck" 'prolog-compile-region)
  958. (define-key map "\C-cK" 'prolog-compile-buffer))
  959. (define-key map "\C-c\C-p" 'prolog-consult-predicate)
  960. (define-key map "\C-c\C-r" 'prolog-consult-region)
  961. (define-key map "\C-c\C-b" 'prolog-consult-buffer)
  962. (define-key map "\C-c\C-f" 'prolog-consult-file)
  963. (define-key map "\C-c\C-cp" 'prolog-compile-predicate)
  964. (define-key map "\C-c\C-cr" 'prolog-compile-region)
  965. (define-key map "\C-c\C-cb" 'prolog-compile-buffer)
  966. (define-key map "\C-c\C-cf" 'prolog-compile-file))
  967. ;; Inherited from the old prolog.el.
  968. (define-key map "\e\C-x" 'prolog-consult-region)
  969. (define-key map "\C-c\C-l" 'prolog-consult-file)
  970. (define-key map "\C-c\C-z" 'run-prolog))
  971. (defun prolog-mode-keybindings-inferior (_map)
  972. "Define keybindings for inferior Prolog mode in MAP."
  973. ;; No inferior mode specific keybindings now.
  974. )
  975. (defvar prolog-mode-map
  976. (let ((map (make-sparse-keymap)))
  977. (prolog-mode-keybindings-common map)
  978. (prolog-mode-keybindings-edit map)
  979. map))
  980. (defvar prolog-mode-hook nil
  981. "List of functions to call after the prolog mode has initialized.")
  982. ;;;###autoload
  983. (define-derived-mode prolog-mode prog-mode "Prolog"
  984. "Major mode for editing Prolog code.
  985. Blank lines and `%%...' separate paragraphs. `%'s starts a comment
  986. line and comments can also be enclosed in /* ... */.
  987. If an optional argument SYSTEM is non-nil, set up mode for the given system.
  988. To find out what version of Prolog mode you are running, enter
  989. `\\[prolog-mode-version]'.
  990. Commands:
  991. \\{prolog-mode-map}"
  992. (setq mode-name (concat "Prolog"
  993. (cond
  994. ((eq prolog-system 'eclipse) "[ECLiPSe]")
  995. ((eq prolog-system 'sicstus) "[SICStus]")
  996. ((eq prolog-system 'swi) "[SWI]")
  997. ((eq prolog-system 'gnu) "[GNU]")
  998. (t ""))))
  999. (prolog-mode-variables)
  1000. (dolist (ar prolog-align-rules) (add-to-list 'align-rules-list ar))
  1001. (add-hook 'post-self-insert-hook #'prolog-post-self-insert nil t)
  1002. ;; `imenu' entry moved to the appropriate hook for consistency.
  1003. ;; Load SICStus debugger if suitable
  1004. (if (and (eq prolog-system 'sicstus)
  1005. (prolog-atleast-version '(3 . 7))
  1006. prolog-use-sicstus-sd)
  1007. (prolog-enable-sicstus-sd))
  1008. (prolog-menu))
  1009. (defvar mercury-mode-map
  1010. (let ((map (make-sparse-keymap)))
  1011. (set-keymap-parent map prolog-mode-map)
  1012. map))
  1013. ;;;###autoload
  1014. (define-derived-mode mercury-mode prolog-mode "Prolog[Mercury]"
  1015. "Major mode for editing Mercury programs.
  1016. Actually this is just customized `prolog-mode'."
  1017. (setq-local prolog-system 'mercury))
  1018. ;;-------------------------------------------------------------------
  1019. ;; Inferior prolog mode
  1020. ;;-------------------------------------------------------------------
  1021. (defvar prolog-inferior-mode-map
  1022. (let ((map (make-sparse-keymap)))
  1023. (prolog-mode-keybindings-common map)
  1024. (prolog-mode-keybindings-inferior map)
  1025. (define-key map [remap self-insert-command]
  1026. 'prolog-inferior-self-insert-command)
  1027. map))
  1028. (defvar prolog-inferior-mode-hook nil
  1029. "List of functions to call after the inferior prolog mode has initialized.")
  1030. (defvar prolog-inferior-error-regexp-alist
  1031. '(;; GNU Prolog used to not follow the GNU standard format.
  1032. ;; ("^\\(.*?\\):\\([0-9]+\\) error: .*(char:\\([0-9]+\\)" 1 2 3)
  1033. ;; SWI-Prolog.
  1034. ("^\\(?:\\?- *\\)?\\(\\(?:ERROR\\|\\(W\\)arning\\): *\\(.*?\\):\\([1-9][0-9]*\\):\\(?:\\([0-9]*\\):\\)?\\)\\(?:$\\| \\)"
  1035. 3 4 5 (2 . nil) 1)
  1036. ;; GNU-Prolog now uses the GNU standard format.
  1037. gnu))
  1038. (defun prolog-inferior-self-insert-command ()
  1039. "Insert the char in the buffer or pass it directly to the process."
  1040. (interactive)
  1041. (let* ((proc (get-buffer-process (current-buffer)))
  1042. (pmark (and proc (marker-position (process-mark proc)))))
  1043. ;; FIXME: the same treatment would be needed for SWI-Prolog, but I can't
  1044. ;; seem to find any way for Emacs to figure out when to use it because
  1045. ;; SWI doesn't include a " ? " or some such recognizable marker.
  1046. (if (and (eq prolog-system 'gnu)
  1047. pmark
  1048. (null current-prefix-arg)
  1049. (eobp)
  1050. (eq (point) pmark)
  1051. (save-excursion
  1052. (goto-char (- pmark 3))
  1053. ;; FIXME: check this comes from the process's output, maybe?
  1054. (looking-at " \\? ")))
  1055. ;; This is GNU prolog waiting to know whether you want more answers
  1056. ;; or not (or abort, etc...). The answer is a single char, not
  1057. ;; a line, so pass this char directly rather than wait for RET to
  1058. ;; send a whole line.
  1059. (comint-send-string proc (string last-command-event))
  1060. (call-interactively 'self-insert-command))))
  1061. (declare-function 'compilation-shell-minor-mode "compile" (&optional arg))
  1062. (defvar compilation-error-regexp-alist)
  1063. (define-derived-mode prolog-inferior-mode comint-mode "Inferior Prolog"
  1064. "Major mode for interacting with an inferior Prolog process.
  1065. The following commands are available:
  1066. \\{prolog-inferior-mode-map}
  1067. Entry to this mode calls the value of `prolog-mode-hook' with no arguments,
  1068. if that value is non-nil. Likewise with the value of `comint-mode-hook'.
  1069. `prolog-mode-hook' is called after `comint-mode-hook'.
  1070. You can send text to the inferior Prolog from other buffers
  1071. using the commands `send-region', `send-string' and \\[prolog-consult-region].
  1072. Commands:
  1073. Tab indents for Prolog; with argument, shifts rest
  1074. of expression rigidly with the current line.
  1075. Paragraphs are separated only by blank lines and '%%'. '%'s start comments.
  1076. Return at end of buffer sends line as input.
  1077. Return not at end copies rest of line to end and sends it.
  1078. \\[comint-delchar-or-maybe-eof] sends end-of-file as input.
  1079. \\[comint-kill-input] and \\[backward-kill-word] are kill commands,
  1080. imitating normal Unix input editing.
  1081. \\[comint-interrupt-subjob] interrupts the shell or its current subjob if any.
  1082. \\[comint-stop-subjob] stops, likewise.
  1083. \\[comint-quit-subjob] sends quit signal, likewise.
  1084. To find out what version of Prolog mode you are running, enter
  1085. `\\[prolog-mode-version]'."
  1086. (require 'compile)
  1087. (setq comint-input-filter 'prolog-input-filter)
  1088. (setq mode-line-process '(": %s"))
  1089. (prolog-mode-variables)
  1090. (setq comint-prompt-regexp (prolog-prompt-regexp))
  1091. (setq-local shell-dirstack-query "pwd.")
  1092. (setq-local compilation-error-regexp-alist
  1093. prolog-inferior-error-regexp-alist)
  1094. (compilation-shell-minor-mode)
  1095. (prolog-inferior-menu))
  1096. (defun prolog-input-filter (str)
  1097. (cond ((string-match "\\`\\s *\\'" str) nil) ;whitespace
  1098. ((not (derived-mode-p 'prolog-inferior-mode)) t)
  1099. ((= (length str) 1) nil) ;one character
  1100. ((string-match "\\`[rf] *[0-9]*\\'" str) nil) ;r(edo) or f(ail)
  1101. (t t)))
  1102. ;; This statement was missing in Emacs 24.1, 24.2, 24.3.
  1103. (define-obsolete-function-alias 'switch-to-prolog 'run-prolog "24.1")
  1104. ;;;###autoload
  1105. (defun run-prolog (arg)
  1106. "Run an inferior Prolog process, input and output via buffer *prolog*.
  1107. With prefix argument ARG, restart the Prolog process if running before."
  1108. (interactive "P")
  1109. ;; FIXME: It should be possible to interactively specify the command to use
  1110. ;; to run prolog.
  1111. (if (and arg (get-process "prolog"))
  1112. (progn
  1113. (process-send-string "prolog" "halt.\n")
  1114. (while (get-process "prolog") (sit-for 0.1))))
  1115. (let ((buff (buffer-name)))
  1116. (if (not (string= buff "*prolog*"))
  1117. (prolog-goto-prolog-process-buffer))
  1118. ;; Load SICStus debugger if suitable
  1119. (if (and (eq prolog-system 'sicstus)
  1120. (prolog-atleast-version '(3 . 7))
  1121. prolog-use-sicstus-sd)
  1122. (prolog-enable-sicstus-sd))
  1123. (prolog-mode-variables)
  1124. (prolog-ensure-process)
  1125. ))
  1126. (defun prolog-inferior-guess-flavor (&optional ignored)
  1127. (setq-local prolog-system
  1128. (when (or (numberp prolog-system) (markerp prolog-system))
  1129. (save-excursion
  1130. (goto-char (1+ prolog-system))
  1131. (cond
  1132. ((looking-at "GNU Prolog") 'gnu)
  1133. ((looking-at "Welcome to SWI-Prolog\\|%.*\\<swi_") 'swi)
  1134. ((looking-at ".*\n") nil) ;There's at least one line.
  1135. (t prolog-system)))))
  1136. (when (symbolp prolog-system)
  1137. (remove-hook 'comint-output-filter-functions
  1138. 'prolog-inferior-guess-flavor t)
  1139. (when prolog-system
  1140. (setq comint-prompt-regexp (prolog-prompt-regexp))
  1141. (if (eq prolog-system 'gnu)
  1142. (setq-local comint-process-echoes t)))))
  1143. (defun prolog-ensure-process (&optional wait)
  1144. "If Prolog process is not running, run it.
  1145. If the optional argument WAIT is non-nil, wait for Prolog prompt specified by
  1146. the variable `prolog-prompt-regexp'."
  1147. (if (null (prolog-program-name))
  1148. (error "This Prolog system has defined no interpreter."))
  1149. (if (comint-check-proc "*prolog*")
  1150. ()
  1151. (with-current-buffer (get-buffer-create "*prolog*")
  1152. (prolog-inferior-mode)
  1153. (apply 'make-comint-in-buffer "prolog" (current-buffer)
  1154. (prolog-program-name) nil (prolog-program-switches))
  1155. (unless prolog-system
  1156. ;; Setup auto-detection.
  1157. (setq-local
  1158. prolog-system
  1159. ;; Force re-detection.
  1160. (let* ((proc (get-buffer-process (current-buffer)))
  1161. (pmark (and proc (marker-position (process-mark proc)))))
  1162. (cond
  1163. ((null pmark) (1- (point-min)))
  1164. ;; The use of insert-before-markers in comint.el together with
  1165. ;; the potential use of comint-truncate-buffer in the output
  1166. ;; filter, means that it's difficult to reliably keep track of
  1167. ;; the buffer position where the process's output started.
  1168. ;; If possible we use a marker at "start - 1", so that
  1169. ;; insert-before-marker at `start' won't shift it. And if not,
  1170. ;; we fall back on using a plain integer.
  1171. ((> pmark (point-min)) (copy-marker (1- pmark)))
  1172. (t (1- pmark)))))
  1173. (add-hook 'comint-output-filter-functions
  1174. 'prolog-inferior-guess-flavor nil t))
  1175. (if wait
  1176. (progn
  1177. (goto-char (point-max))
  1178. (while
  1179. (save-excursion
  1180. (not
  1181. (re-search-backward
  1182. (concat "\\(" (prolog-prompt-regexp) "\\)" "\\=")
  1183. nil t)))
  1184. (sit-for 0.1)))))))
  1185. (defun prolog-inferior-buffer (&optional dont-run)
  1186. (or (get-buffer "*prolog*")
  1187. (unless dont-run
  1188. (prolog-ensure-process)
  1189. (get-buffer "*prolog*"))))
  1190. (defun prolog-process-insert-string (process string)
  1191. "Insert STRING into inferior Prolog buffer running PROCESS."
  1192. ;; Copied from elisp manual, greek to me
  1193. (with-current-buffer (process-buffer process)
  1194. ;; FIXME: Use window-point-insertion-type instead.
  1195. (let ((moving (= (point) (process-mark process))))
  1196. (save-excursion
  1197. ;; Insert the text, moving the process-marker.
  1198. (goto-char (process-mark process))
  1199. (insert string)
  1200. (set-marker (process-mark process) (point)))
  1201. (if moving (goto-char (process-mark process))))))
  1202. ;;------------------------------------------------------------
  1203. ;; Old consulting and compiling functions
  1204. ;;------------------------------------------------------------
  1205. (declare-function compilation-forget-errors "compile" ())
  1206. (declare-function compilation-fake-loc "compile"
  1207. (marker file &optional line col))
  1208. (defun prolog-old-process-region (compilep start end)
  1209. "Process the region limited by START and END positions.
  1210. If COMPILEP is non-nil then use compilation, otherwise consulting."
  1211. (prolog-ensure-process)
  1212. ;(let ((tmpfile prolog-temp-filename)
  1213. (let ((tmpfile (prolog-temporary-file))
  1214. ;(process (get-process "prolog"))
  1215. (first-line (1+ (count-lines
  1216. (point-min)
  1217. (save-excursion
  1218. (goto-char start)
  1219. (point))))))
  1220. (write-region start end tmpfile)
  1221. (setq start (copy-marker start))
  1222. (with-current-buffer (prolog-inferior-buffer)
  1223. (compilation-forget-errors)
  1224. (compilation-fake-loc start tmpfile))
  1225. (process-send-string
  1226. "prolog" (prolog-build-prolog-command
  1227. compilep tmpfile (prolog-bsts buffer-file-name)
  1228. first-line))
  1229. (prolog-goto-prolog-process-buffer)))
  1230. (defun prolog-old-process-predicate (compilep)
  1231. "Process the predicate around point.
  1232. If COMPILEP is non-nil then use compilation, otherwise consulting."
  1233. (prolog-old-process-region
  1234. compilep (prolog-pred-start) (prolog-pred-end)))
  1235. (defun prolog-old-process-buffer (compilep)
  1236. "Process the entire buffer.
  1237. If COMPILEP is non-nil then use compilation, otherwise consulting."
  1238. (prolog-old-process-region compilep (point-min) (point-max)))
  1239. (defun prolog-old-process-file (compilep)
  1240. "Process the file of the current buffer.
  1241. If COMPILEP is non-nil then use compilation, otherwise consulting."
  1242. (save-some-buffers)
  1243. (prolog-ensure-process)
  1244. (with-current-buffer (prolog-inferior-buffer)
  1245. (compilation-forget-errors))
  1246. (process-send-string
  1247. "prolog" (prolog-build-prolog-command
  1248. compilep buffer-file-name
  1249. (prolog-bsts buffer-file-name)))
  1250. (prolog-goto-prolog-process-buffer))
  1251. ;;------------------------------------------------------------
  1252. ;; Consulting and compiling
  1253. ;;------------------------------------------------------------
  1254. ;; Interactive interface functions, used by both the standard
  1255. ;; and the experimental consultation and compilation functions
  1256. (defun prolog-consult-file ()
  1257. "Consult file of current buffer."
  1258. (interactive)
  1259. (if prolog-use-standard-consult-compile-method-flag
  1260. (prolog-old-process-file nil)
  1261. (prolog-consult-compile-file nil)))
  1262. (defun prolog-consult-buffer ()
  1263. "Consult buffer."
  1264. (interactive)
  1265. (if prolog-use-standard-consult-compile-method-flag
  1266. (prolog-old-process-buffer nil)
  1267. (prolog-consult-compile-buffer nil)))
  1268. (defun prolog-consult-region (beg end)
  1269. "Consult region between BEG and END."
  1270. (interactive "r")
  1271. (if prolog-use-standard-consult-compile-method-flag
  1272. (prolog-old-process-region nil beg end)
  1273. (prolog-consult-compile-region nil beg end)))
  1274. (defun prolog-consult-predicate ()
  1275. "Consult the predicate around current point."
  1276. (interactive)
  1277. (if prolog-use-standard-consult-compile-method-flag
  1278. (prolog-old-process-predicate nil)
  1279. (prolog-consult-compile-predicate nil)))
  1280. (defun prolog-compile-file ()
  1281. "Compile file of current buffer."
  1282. (interactive)
  1283. (if prolog-use-standard-consult-compile-method-flag
  1284. (prolog-old-process-file t)
  1285. (prolog-consult-compile-file t)))
  1286. (defun prolog-compile-buffer ()
  1287. "Compile buffer."
  1288. (interactive)
  1289. (if prolog-use-standard-consult-compile-method-flag
  1290. (prolog-old-process-buffer t)
  1291. (prolog-consult-compile-buffer t)))
  1292. (defun prolog-compile-region (beg end)
  1293. "Compile region between BEG and END."
  1294. (interactive "r")
  1295. (if prolog-use-standard-consult-compile-method-flag
  1296. (prolog-old-process-region t beg end)
  1297. (prolog-consult-compile-region t beg end)))
  1298. (defun prolog-compile-predicate ()
  1299. "Compile the predicate around current point."
  1300. (interactive)
  1301. (if prolog-use-standard-consult-compile-method-flag
  1302. (prolog-old-process-predicate t)
  1303. (prolog-consult-compile-predicate t)))
  1304. (defun prolog-buffer-module ()
  1305. "Select Prolog module name appropriate for current buffer.
  1306. Bases decision on buffer contents (-*- line)."
  1307. ;; Look for -*- ... module: MODULENAME; ... -*-
  1308. (let (beg end)
  1309. (save-excursion
  1310. (goto-char (point-min))
  1311. (skip-chars-forward " \t")
  1312. (and (search-forward "-*-" (line-end-position) t)
  1313. (progn
  1314. (skip-chars-forward " \t")
  1315. (setq beg (point))
  1316. (search-forward "-*-" (line-end-position) t))
  1317. (progn
  1318. (forward-char -3)
  1319. (skip-chars-backward " \t")
  1320. (setq end (point))
  1321. (goto-char beg)
  1322. (and (let ((case-fold-search t))
  1323. (search-forward "module:" end t))
  1324. (progn
  1325. (skip-chars-forward " \t")
  1326. (setq beg (point))
  1327. (if (search-forward ";" end t)
  1328. (forward-char -1)
  1329. (goto-char end))
  1330. (skip-chars-backward " \t")
  1331. (buffer-substring beg (point)))))))))
  1332. (defun prolog-build-prolog-command (compilep file buffername
  1333. &optional first-line)
  1334. "Make Prolog command for FILE compilation/consulting.
  1335. If COMPILEP is non-nil, consider compilation, otherwise consulting."
  1336. (let* ((compile-string
  1337. ;; FIXME: If the process is not running yet, the auto-detection of
  1338. ;; prolog-system won't help here, so we should make sure
  1339. ;; we first run Prolog and then build the command.
  1340. (if compilep (prolog-compile-string) (prolog-consult-string)))
  1341. (module (prolog-buffer-module))
  1342. (file-name (concat "'" (prolog-bsts file) "'"))
  1343. (module-name (if module (concat "'" module "'")))
  1344. (module-file (if module
  1345. (concat module-name ":" file-name)
  1346. file-name))
  1347. strbeg strend
  1348. (lineoffset (if first-line
  1349. (- first-line 1)
  1350. 0)))
  1351. ;; Assure that there is a buffer name
  1352. (if (not buffername)
  1353. (error "The buffer is not saved"))
  1354. (if (not (string-match "\\`'.*'\\'" buffername)) ; Add quotes
  1355. (setq buffername (concat "'" buffername "'")))
  1356. (while (string-match "%m" compile-string)
  1357. (setq strbeg (substring compile-string 0 (match-beginning 0)))
  1358. (setq strend (substring compile-string (match-end 0)))
  1359. (setq compile-string (concat strbeg module-file strend)))
  1360. ;; FIXME: The code below will %-expand any %[fbl] that appears in
  1361. ;; module-file.
  1362. (while (string-match "%f" compile-string)
  1363. (setq strbeg (substring compile-string 0 (match-beginning 0)))
  1364. (setq strend (substring compile-string (match-end 0)))
  1365. (setq compile-string (concat strbeg file-name strend)))
  1366. (while (string-match "%b" compile-string)
  1367. (setq strbeg (substring compile-string 0 (match-beginning 0)))
  1368. (setq strend (substring compile-string (match-end 0)))
  1369. (setq compile-string (concat strbeg buffername strend)))
  1370. (while (string-match "%l" compile-string)
  1371. (setq strbeg (substring compile-string 0 (match-beginning 0)))
  1372. (setq strend (substring compile-string (match-end 0)))
  1373. (setq compile-string (concat strbeg (format "%d" lineoffset) strend)))
  1374. (concat compile-string "\n")))
  1375. ;; The rest of this page is experimental code!
  1376. ;; Global variables for process filter function
  1377. (defvar prolog-process-flag nil
  1378. "Non-nil means that a prolog task (i.e. a consultation or compilation job)
  1379. is running.")
  1380. (defvar prolog-consult-compile-output ""
  1381. "Hold the unprocessed output from the current prolog task.")
  1382. (defvar prolog-consult-compile-first-line 1
  1383. "The number of the first line of the file to consult/compile.
  1384. Used for temporary files.")
  1385. (defvar prolog-consult-compile-file nil
  1386. "The file to compile/consult (can be a temporary file).")
  1387. (defvar prolog-consult-compile-real-file nil
  1388. "The file name of the buffer to compile/consult.")
  1389. (defvar compilation-parse-errors-function)
  1390. (defun prolog-consult-compile (compilep file &optional first-line)
  1391. "Consult/compile FILE.
  1392. If COMPILEP is non-nil, perform compilation, otherwise perform CONSULTING.
  1393. COMMAND is a string described by the variables `prolog-consult-string'
  1394. and `prolog-compile-string'.
  1395. Optional argument FIRST-LINE is the number of the first line in the compiled
  1396. region.
  1397. This function must be called from the source code buffer."
  1398. (if prolog-process-flag
  1399. (error "Another Prolog task is running."))
  1400. (prolog-ensure-process t)
  1401. (let* ((buffer (get-buffer-create prolog-compilation-buffer))
  1402. (real-file buffer-file-name)
  1403. (command-string (prolog-build-prolog-command compilep file
  1404. real-file first-line))
  1405. (process (get-process "prolog")))
  1406. (with-current-buffer buffer
  1407. (delete-region (point-min) (point-max))
  1408. ;; FIXME: Wasn't this supposed to use prolog-inferior-mode?
  1409. (compilation-mode)
  1410. ;; FIXME: This doesn't seem to cooperate well with new(ish) compile.el.
  1411. ;; Setting up font-locking for this buffer
  1412. (setq-local font-lock-defaults
  1413. '(prolog-font-lock-keywords nil nil ((?_ . "w"))))
  1414. (if (eq prolog-system 'sicstus)
  1415. ;; FIXME: This looks really problematic: not only is this using
  1416. ;; the old compilation-parse-errors-function, but
  1417. ;; prolog-parse-sicstus-compilation-errors only accepts one argument
  1418. ;; whereas compile.el calls it with 2 (and did so at least since
  1419. ;; Emacs-20).
  1420. (setq-local compilation-parse-errors-function
  1421. 'prolog-parse-sicstus-compilation-errors))
  1422. (setq buffer-read-only nil)
  1423. (insert command-string "\n"))
  1424. (display-buffer buffer)
  1425. (setq prolog-process-flag t
  1426. prolog-consult-compile-output ""
  1427. prolog-consult-compile-first-line (if first-line (1- first-line) 0)
  1428. prolog-consult-compile-file file
  1429. prolog-consult-compile-real-file (if (string=
  1430. file buffer-file-name)
  1431. nil
  1432. real-file))
  1433. (with-current-buffer buffer
  1434. (goto-char (point-max))
  1435. (add-function :override (process-filter process)
  1436. #'prolog-consult-compile-filter)
  1437. (process-send-string "prolog" command-string)
  1438. ;; (prolog-build-prolog-command compilep file real-file first-line))
  1439. (while (and prolog-process-flag
  1440. (accept-process-output process 10)) ; 10 secs is ok?
  1441. (sit-for 0.1)
  1442. (unless (get-process "prolog")
  1443. (setq prolog-process-flag nil)))
  1444. (insert (if compilep
  1445. "\nCompilation finished.\n"
  1446. "\nConsulted.\n"))
  1447. (remove-function (process-filter process)
  1448. #'prolog-consult-compile-filter))))
  1449. (defvar compilation-error-list)
  1450. (defun prolog-parse-sicstus-compilation-errors (limit)
  1451. "Parse the prolog compilation buffer for errors.
  1452. Argument LIMIT is a buffer position limiting searching.
  1453. For use with the `compilation-parse-errors-function' variable."
  1454. (setq compilation-error-list nil)
  1455. (message "Parsing SICStus error messages...")
  1456. (let (filepath dir file errorline)
  1457. (while
  1458. (re-search-backward
  1459. "{\\([a-zA-Z ]* ERROR\\|Warning\\):.* in line[s ]*\\([0-9]+\\)"
  1460. limit t)
  1461. (setq errorline (string-to-number (match-string 2)))
  1462. (save-excursion
  1463. (re-search-backward
  1464. "{\\(consulting\\|compiling\\|processing\\) \\(.*\\)\\.\\.\\.}"
  1465. limit t)
  1466. (setq filepath (match-string 2)))
  1467. ;; ###### Does this work with SICStus under Windows
  1468. ;; (i.e. backslashes and stuff?)
  1469. (if (string-match "\\(.*/\\)\\([^/]*\\)$" filepath)
  1470. (progn
  1471. (setq dir (match-string 1 filepath))
  1472. (setq file (match-string 2 filepath))))
  1473. (setq compilation-error-list
  1474. (cons
  1475. (cons (save-excursion
  1476. (beginning-of-line)
  1477. (point-marker))
  1478. (list (list file dir) errorline))
  1479. compilation-error-list)
  1480. ))
  1481. ))
  1482. (defun prolog-consult-compile-filter (process output)
  1483. "Filter function for Prolog compilation PROCESS.
  1484. Argument OUTPUT is a name of the output file."
  1485. ;;(message "start")
  1486. (setq prolog-consult-compile-output
  1487. (concat prolog-consult-compile-output output))
  1488. ;;(message "pccf1: %s" prolog-consult-compile-output)
  1489. ;; Iterate through the lines of prolog-consult-compile-output
  1490. (let (outputtype)
  1491. (while (and prolog-process-flag
  1492. (or
  1493. ;; Trace question
  1494. (progn
  1495. (setq outputtype 'trace)
  1496. (and (eq prolog-system 'sicstus)
  1497. (string-match
  1498. "^[ \t]*[0-9]+[ \t]*[0-9]+[ \t]*Call:.*? "
  1499. prolog-consult-compile-output)))
  1500. ;; Match anything
  1501. (progn
  1502. (setq outputtype 'normal)
  1503. (string-match "^.*\n" prolog-consult-compile-output))
  1504. ))
  1505. ;;(message "outputtype: %s" outputtype)
  1506. (setq output (match-string 0 prolog-consult-compile-output))
  1507. ;; remove the text in output from prolog-consult-compile-output
  1508. (setq prolog-consult-compile-output
  1509. (substring prolog-consult-compile-output (length output)))
  1510. ;;(message "pccf2: %s" prolog-consult-compile-output)
  1511. ;; If temporary files were used, then we change the error
  1512. ;; messages to point to the original source file.
  1513. ;; FIXME: Use compilation-fake-loc instead.
  1514. (cond
  1515. ;; If the prolog process was in trace mode then it requires
  1516. ;; user input
  1517. ((and (eq prolog-system 'sicstus)
  1518. (eq outputtype 'trace))
  1519. (let ((input (concat (read-string output) "\n")))
  1520. (process-send-string process input)
  1521. (setq output (concat output input))))
  1522. ((eq prolog-system 'sicstus)
  1523. (if (and prolog-consult-compile-real-file
  1524. (string-match
  1525. "\\({.*:.* in line[s ]*\\)\\([0-9]+\\)-\\([0-9]+\\)" output))
  1526. (setq output (replace-match
  1527. ;; Adds a {processing ...} line so that
  1528. ;; `prolog-parse-sicstus-compilation-errors'
  1529. ;; finds the real file instead of the temporary one.
  1530. ;; Also fixes the line numbers.
  1531. (format "Added by Emacs: {processing %s...}\n%s%d-%d"
  1532. prolog-consult-compile-real-file
  1533. (match-string 1 output)
  1534. (+ prolog-consult-compile-first-line
  1535. (string-to-number
  1536. (match-string 2 output)))
  1537. (+ prolog-consult-compile-first-line
  1538. (string-to-number
  1539. (match-string 3 output))))
  1540. t t output)))
  1541. )
  1542. ((eq prolog-system 'swi)
  1543. (if (and prolog-consult-compile-real-file
  1544. (string-match (format
  1545. "%s\\([ \t]*:[ \t]*\\)\\([0-9]+\\)"
  1546. prolog-consult-compile-file)
  1547. output))
  1548. (setq output (replace-match
  1549. ;; Real filename + text + fixed linenum
  1550. (format "%s%s%d"
  1551. prolog-consult-compile-real-file
  1552. (match-string 1 output)
  1553. (+ prolog-consult-compile-first-line
  1554. (string-to-number
  1555. (match-string 2 output))))
  1556. t t output)))
  1557. )
  1558. (t ())
  1559. )
  1560. ;; Write the output in the *prolog-compilation* buffer
  1561. (insert output)))
  1562. ;; If the prompt is visible, then the task is finished
  1563. (if (string-match (prolog-prompt-regexp) prolog-consult-compile-output)
  1564. (setq prolog-process-flag nil)))
  1565. (defun prolog-consult-compile-file (compilep)
  1566. "Consult/compile file of current buffer.
  1567. If COMPILEP is non-nil, compile, otherwise consult."
  1568. (let ((file buffer-file-name))
  1569. (if file
  1570. (progn
  1571. (save-some-buffers)
  1572. (prolog-consult-compile compilep file))
  1573. (prolog-consult-compile-region compilep (point-min) (point-max)))))
  1574. (defun prolog-consult-compile-buffer (compilep)
  1575. "Consult/compile current buffer.
  1576. If COMPILEP is non-nil, compile, otherwise consult."
  1577. (prolog-consult-compile-region compilep (point-min) (point-max)))
  1578. (defun prolog-consult-compile-region (compilep beg end)
  1579. "Consult/compile region between BEG and END.
  1580. If COMPILEP is non-nil, compile, otherwise consult."
  1581. ;(let ((file prolog-temp-filename)
  1582. (let ((file (prolog-bsts (prolog-temporary-file)))
  1583. (lines (count-lines 1 beg)))
  1584. (write-region beg end file nil 'no-message)
  1585. (write-region "\n" nil file t 'no-message)
  1586. (prolog-consult-compile compilep file
  1587. (if (bolp) (1+ lines) lines))
  1588. (delete-file file)))
  1589. (defun prolog-consult-compile-predicate (compilep)
  1590. "Consult/compile the predicate around current point.
  1591. If COMPILEP is non-nil, compile, otherwise consult."
  1592. (prolog-consult-compile-region
  1593. compilep (prolog-pred-start) (prolog-pred-end)))
  1594. ;;-------------------------------------------------------------------
  1595. ;; Font-lock stuff
  1596. ;;-------------------------------------------------------------------
  1597. ;; Auxiliary functions
  1598. (defun prolog-font-lock-object-matcher (bound)
  1599. "Find SICStus objects method name for font lock.
  1600. Argument BOUND is a buffer position limiting searching."
  1601. (let (point
  1602. (case-fold-search nil))
  1603. (while (and (not point)
  1604. (re-search-forward "\\(::[ \t\n]*{\\|&\\)[ \t]*"
  1605. bound t))
  1606. (while (or (re-search-forward "\\=\n[ \t]*" bound t)
  1607. (re-search-forward "\\=%.*" bound t)
  1608. (and (re-search-forward "\\=/\\*" bound t)
  1609. (re-search-forward "\\*/[ \t]*" bound t))))
  1610. (setq point (re-search-forward
  1611. (format "\\=\\(%s\\)" prolog-atom-regexp)
  1612. bound t)))
  1613. point))
  1614. (defsubst prolog-face-name-p (facename)
  1615. ;; Return t if FACENAME is the name of a face. This method is
  1616. ;; necessary since facep in XEmacs only returns t for the actual
  1617. ;; face objects (while it's only their names that are used just
  1618. ;; about anywhere else) without providing a predicate that tests
  1619. ;; face names. This function (including the above commentary) is
  1620. ;; borrowed from cc-mode.
  1621. (memq facename (face-list)))
  1622. ;; Set everything up
  1623. (defun prolog-font-lock-keywords ()
  1624. "Set up font lock keywords for the current Prolog system."
  1625. ;;(when window-system
  1626. (require 'font-lock)
  1627. ;; Define Prolog faces
  1628. (defface prolog-redo-face
  1629. '((((class grayscale)) (:italic t))
  1630. (((class color)) (:foreground "darkorchid"))
  1631. (t (:italic t)))
  1632. "Prolog mode face for highlighting redo trace lines."
  1633. :group 'prolog-faces)
  1634. (defface prolog-exit-face
  1635. '((((class grayscale)) (:underline t))
  1636. (((class color) (background dark)) (:foreground "green"))
  1637. (((class color) (background light)) (:foreground "ForestGreen"))
  1638. (t (:underline t)))
  1639. "Prolog mode face for highlighting exit trace lines."
  1640. :group 'prolog-faces)
  1641. (defface prolog-exception-face
  1642. '((((class grayscale)) (:bold t :italic t :underline t))
  1643. (((class color)) (:bold t :foreground "black" :background "Khaki"))
  1644. (t (:bold t :italic t :underline t)))
  1645. "Prolog mode face for highlighting exception trace lines."
  1646. :group 'prolog-faces)
  1647. (defface prolog-warning-face
  1648. '((((class grayscale)) (:underline t))
  1649. (((class color) (background dark)) (:foreground "blue"))
  1650. (((class color) (background light)) (:foreground "MidnightBlue"))
  1651. (t (:underline t)))
  1652. "Face name to use for compiler warnings."
  1653. :group 'prolog-faces)
  1654. (defface prolog-builtin-face
  1655. '((((class color) (background light)) (:foreground "Purple"))
  1656. (((class color) (background dark)) (:foreground "Cyan"))
  1657. (((class grayscale) (background light))
  1658. :foreground "LightGray" :bold t)
  1659. (((class grayscale) (background dark)) (:foreground "DimGray" :bold t))
  1660. (t (:bold t)))
  1661. "Face name to use for compiler warnings."
  1662. :group 'prolog-faces)
  1663. (defvar prolog-warning-face
  1664. (if (prolog-face-name-p 'font-lock-warning-face)
  1665. 'font-lock-warning-face
  1666. 'prolog-warning-face)
  1667. "Face name to use for built in predicates.")
  1668. (defvar prolog-builtin-face
  1669. (if (prolog-face-name-p 'font-lock-builtin-face)
  1670. 'font-lock-builtin-face
  1671. 'prolog-builtin-face)
  1672. "Face name to use for built in predicates.")
  1673. (defvar prolog-redo-face 'prolog-redo-face
  1674. "Face name to use for redo trace lines.")
  1675. (defvar prolog-exit-face 'prolog-exit-face
  1676. "Face name to use for exit trace lines.")
  1677. (defvar prolog-exception-face 'prolog-exception-face
  1678. "Face name to use for exception trace lines.")
  1679. ;; Font Lock Patterns
  1680. (let (
  1681. ;; "Native" Prolog patterns
  1682. (head-predicates
  1683. (list (format "^\\(%s\\)\\((\\|[ \t]*:-\\)" prolog-atom-regexp)
  1684. 1 font-lock-function-name-face))
  1685. ;(list (format "^%s" prolog-atom-regexp)
  1686. ; 0 font-lock-function-name-face))
  1687. (head-predicates-1
  1688. (list (format "\\.[ \t]*\\(%s\\)" prolog-atom-regexp)
  1689. 1 font-lock-function-name-face) )
  1690. (variables
  1691. '("\\<\\([_A-Z][a-zA-Z0-9_]*\\)"
  1692. 1 font-lock-variable-name-face))
  1693. (important-elements
  1694. (list (if (eq prolog-system 'mercury)
  1695. "[][}{;|]\\|\\\\[+=]\\|<?=>?"
  1696. "[][}{!;|]\\|\\*->")
  1697. 0 'font-lock-keyword-face))
  1698. (important-elements-1
  1699. '("[^-*]\\(->\\)" 1 font-lock-keyword-face))
  1700. (predspecs ; module:predicate/cardinality
  1701. (list (format "\\<\\(%s:\\|\\)%s/[0-9]+"
  1702. prolog-atom-regexp prolog-atom-regexp)
  1703. 0 font-lock-function-name-face 'prepend))
  1704. (keywords ; directives (queries)
  1705. (list
  1706. (if (eq prolog-system 'mercury)
  1707. (concat
  1708. "\\<\\("
  1709. (regexp-opt prolog-keywords-i)
  1710. "\\|"
  1711. (regexp-opt
  1712. prolog-determinism-specificators-i)
  1713. "\\)\\>")
  1714. (concat
  1715. "^[?:]- *\\("
  1716. (regexp-opt prolog-keywords-i)
  1717. "\\)\\>"))
  1718. 1 prolog-builtin-face))
  1719. ;; SICStus specific patterns
  1720. (sicstus-object-methods
  1721. (if (eq prolog-system 'sicstus)
  1722. '(prolog-font-lock-object-matcher
  1723. 1 font-lock-function-name-face)))
  1724. ;; Mercury specific patterns
  1725. (types
  1726. (if (eq prolog-system 'mercury)
  1727. (list
  1728. (regexp-opt prolog-types-i 'words)
  1729. 0 'font-lock-type-face)))
  1730. (modes
  1731. (if (eq prolog-system 'mercury)
  1732. (list
  1733. (regexp-opt prolog-mode-specificators-i 'words)
  1734. 0 'font-lock-constant-face)))
  1735. (directives
  1736. (if (eq prolog-system 'mercury)
  1737. (list
  1738. (regexp-opt prolog-directives-i 'words)
  1739. 0 'prolog-warning-face)))
  1740. ;; Inferior mode specific patterns
  1741. (prompt
  1742. ;; FIXME: Should be handled by comint already.
  1743. (list (prolog-prompt-regexp) 0 'font-lock-keyword-face))
  1744. (trace-exit
  1745. ;; FIXME: Add to compilation-error-regexp-alist instead.
  1746. (cond
  1747. ((eq prolog-system 'sicstus)
  1748. '("[ \t]*[0-9]+[ \t]+[0-9]+[ \t]*\\(Exit\\):"
  1749. 1 prolog-exit-face))
  1750. ((eq prolog-system 'swi)
  1751. '("[ \t]*\\(Exit\\):[ \t]*([ \t0-9]*)" 1 prolog-exit-face))
  1752. (t nil)))
  1753. (trace-fail
  1754. ;; FIXME: Add to compilation-error-regexp-alist instead.
  1755. (cond
  1756. ((eq prolog-system 'sicstus)
  1757. '("[ \t]*[0-9]+[ \t]+[0-9]+[ \t]*\\(Fail\\):"
  1758. 1 prolog-warning-face))
  1759. ((eq prolog-system 'swi)
  1760. '("[ \t]*\\(Fail\\):[ \t]*([ \t0-9]*)" 1 prolog-warning-face))
  1761. (t nil)))
  1762. (trace-redo
  1763. ;; FIXME: Add to compilation-error-regexp-alist instead.
  1764. (cond
  1765. ((eq prolog-system 'sicstus)
  1766. '("[ \t]*[0-9]+[ \t]+[0-9]+[ \t]*\\(Redo\\):"
  1767. 1 prolog-redo-face))
  1768. ((eq prolog-system 'swi)
  1769. '("[ \t]*\\(Redo\\):[ \t]*([ \t0-9]*)" 1 prolog-redo-face))
  1770. (t nil)))
  1771. (trace-call
  1772. ;; FIXME: Add to compilation-error-regexp-alist instead.
  1773. (cond
  1774. ((eq prolog-system 'sicstus)
  1775. '("[ \t]*[0-9]+[ \t]+[0-9]+[ \t]*\\(Call\\):"
  1776. 1 font-lock-function-name-face))
  1777. ((eq prolog-system 'swi)
  1778. '("[ \t]*\\(Call\\):[ \t]*([ \t0-9]*)"
  1779. 1 font-lock-function-name-face))
  1780. (t nil)))
  1781. (trace-exception
  1782. ;; FIXME: Add to compilation-error-regexp-alist instead.
  1783. (cond
  1784. ((eq prolog-system 'sicstus)
  1785. '("[ \t]*[0-9]+[ \t]+[0-9]+[ \t]*\\(Exception\\):"
  1786. 1 prolog-exception-face))
  1787. ((eq prolog-system 'swi)
  1788. '("[ \t]*\\(Exception\\):[ \t]*([ \t0-9]*)"
  1789. 1 prolog-exception-face))
  1790. (t nil)))
  1791. (error-message-identifier
  1792. ;; FIXME: Add to compilation-error-regexp-alist instead.
  1793. (cond
  1794. ((eq prolog-system 'sicstus)
  1795. '("{\\([A-Z]* ?ERROR:\\)" 1 prolog-exception-face prepend))
  1796. ((eq prolog-system 'swi)
  1797. '("^[[]\\(WARNING:\\)" 1 prolog-builtin-face prepend))
  1798. (t nil)))
  1799. (error-whole-messages
  1800. ;; FIXME: Add to compilation-error-regexp-alist instead.
  1801. (cond
  1802. ((eq prolog-system 'sicstus)
  1803. '("{\\([A-Z]* ?ERROR:.*\\)}[ \t]*$"
  1804. 1 font-lock-comment-face append))
  1805. ((eq prolog-system 'swi)
  1806. '("^[[]WARNING:[^]]*[]]$" 0 font-lock-comment-face append))
  1807. (t nil)))
  1808. (error-warning-messages
  1809. ;; FIXME: Add to compilation-error-regexp-alist instead.
  1810. ;; Mostly errors that SICStus asks the user about how to solve,
  1811. ;; such as "NAME CLASH:" for example.
  1812. (cond
  1813. ((eq prolog-system 'sicstus)
  1814. '("^[A-Z ]*[A-Z]+:" 0 prolog-warning-face))
  1815. (t nil)))
  1816. (warning-messages
  1817. ;; FIXME: Add to compilation-error-regexp-alist instead.
  1818. (cond
  1819. ((eq prolog-system 'sicstus)
  1820. '("\\({ ?\\(Warning\\|WARNING\\) ?:.*}\\)[ \t]*$"
  1821. 2 prolog-warning-face prepend))
  1822. (t nil))))
  1823. ;; Make font lock list
  1824. (delq
  1825. nil
  1826. (cond
  1827. ((eq major-mode 'prolog-mode)
  1828. (list
  1829. head-predicates
  1830. head-predicates-1
  1831. variables
  1832. important-elements
  1833. important-elements-1
  1834. predspecs
  1835. keywords
  1836. sicstus-object-methods
  1837. types
  1838. modes
  1839. directives))
  1840. ((eq major-mode 'prolog-inferior-mode)
  1841. (list
  1842. prompt
  1843. error-message-identifier
  1844. error-whole-messages
  1845. error-warning-messages
  1846. warning-messages
  1847. predspecs
  1848. trace-exit
  1849. trace-fail
  1850. trace-redo
  1851. trace-call
  1852. trace-exception))
  1853. ((eq major-mode 'compilation-mode)
  1854. (list
  1855. error-message-identifier
  1856. error-whole-messages
  1857. error-warning-messages
  1858. warning-messages
  1859. predspecs))))
  1860. ))
  1861. (defun prolog-find-unmatched-paren ()
  1862. "Return the column of the last unmatched left parenthesis."
  1863. (save-excursion
  1864. (goto-char (or (car (nth 9 (syntax-ppss))) (point-min)))
  1865. (current-column)))
  1866. (defun prolog-paren-balance ()
  1867. "Return the parenthesis balance of the current line.
  1868. A return value of N means N more left parentheses than right ones."
  1869. (save-excursion
  1870. (car (parse-partial-sexp (line-beginning-position)
  1871. (line-end-position)))))
  1872. (defun prolog-electric--if-then-else ()
  1873. "Insert spaces after the opening parenthesis, \"then\" (->) and \"else\" (;) branches.
  1874. Spaces are inserted if all preceding objects on the line are
  1875. whitespace characters, parentheses, or then/else branches."
  1876. (when prolog-electric-if-then-else-flag
  1877. (save-excursion
  1878. (let ((regexp (concat "(\\|" prolog-left-indent-regexp))
  1879. level)
  1880. (beginning-of-line)
  1881. (skip-chars-forward " \t")
  1882. ;; Treat "( If -> " lines specially.
  1883. ;;(setq incr (if (looking-at "(.*->")
  1884. ;; 2
  1885. ;; prolog-paren-indent))
  1886. ;; work on all subsequent "->", "(", ";"
  1887. (while (looking-at regexp)
  1888. (goto-char (match-end 0))
  1889. (setq level (+ (prolog-find-unmatched-paren) prolog-paren-indent))
  1890. ;; Remove old white space
  1891. (let ((start (point)))
  1892. (skip-chars-forward " \t")
  1893. (delete-region start (point)))
  1894. (indent-to level)
  1895. (skip-chars-forward " \t"))
  1896. ))
  1897. (when (save-excursion
  1898. (backward-char 2)
  1899. (looking-at "\\s ;\\|\\s (\\|->")) ; (looking-at "\\s \\((\\|;\\)"))
  1900. (skip-chars-forward " \t"))
  1901. ))
  1902. ;;;; Comment filling
  1903. (defun prolog-comment-limits ()
  1904. "Return the current comment limits plus the comment type (block or line).
  1905. The comment limits are the range of a block comment or the range that
  1906. contains all adjacent line comments (i.e. all comments that starts in
  1907. the same column with no empty lines or non-whitespace characters
  1908. between them)."
  1909. (let ((here (point))
  1910. lit-limits-b lit-limits-e lit-type beg end
  1911. )
  1912. (save-restriction
  1913. ;; Widen to catch comment limits correctly.
  1914. (widen)
  1915. (setq end (line-end-position)
  1916. beg (line-beginning-position))
  1917. (save-excursion
  1918. (beginning-of-line)
  1919. (setq lit-type (if (search-forward-regexp "%" end t) 'line 'block))
  1920. ; (setq lit-type 'line)
  1921. ;(if (search-forward-regexp "^[ \t]*%" end t)
  1922. ; (setq lit-type 'line)
  1923. ; (if (not (search-forward-regexp "%" end t))
  1924. ; (setq lit-type 'block)
  1925. ; (if (not (= (forward-line 1) 0))
  1926. ; (setq lit-type 'block)
  1927. ; (setq done t
  1928. ; ret (prolog-comment-limits)))
  1929. ; ))
  1930. (if (eq lit-type 'block)
  1931. (progn
  1932. (goto-char here)
  1933. (when (looking-at "/\\*") (forward-char 2))
  1934. (when (and (looking-at "\\*") (> (point) (point-min))
  1935. (forward-char -1) (looking-at "/"))
  1936. (forward-char 1))
  1937. (when (save-excursion (search-backward "/*" nil t))
  1938. (list (save-excursion (search-backward "/*") (point))
  1939. (or (search-forward "*/" nil t) (point-max)) lit-type)))
  1940. ;; line comment
  1941. (setq lit-limits-b (- (point) 1)
  1942. lit-limits-e end)
  1943. (condition-case nil
  1944. (if (progn (goto-char lit-limits-b)
  1945. (looking-at "%"))
  1946. (let ((col (current-column)) done)
  1947. (setq beg (point)
  1948. end lit-limits-e)
  1949. ;; Always at the beginning of the comment
  1950. ;; Go backward now
  1951. (beginning-of-line)
  1952. (while (and (zerop (setq done (forward-line -1)))
  1953. (search-forward-regexp "^[ \t]*%"
  1954. (line-end-position) t)
  1955. (= (+ 1 col) (current-column)))
  1956. (setq beg (- (point) 1)))
  1957. (when (= done 0)
  1958. (forward-line 1))
  1959. ;; We may have a line with code above...
  1960. (when (and (zerop (setq done (forward-line -1)))
  1961. (search-forward "%" (line-end-position) t)
  1962. (= (+ 1 col) (current-column)))
  1963. (setq beg (- (point) 1)))
  1964. (when (= done 0)
  1965. (forward-line 1))
  1966. ;; Go forward
  1967. (goto-char lit-limits-b)
  1968. (beginning-of-line)
  1969. (while (and (zerop (forward-line 1))
  1970. (search-forward-regexp "^[ \t]*%"
  1971. (line-end-position) t)
  1972. (= (+ 1 col) (current-column)))
  1973. (setq end (line-end-position)))
  1974. (list beg end lit-type))
  1975. (list lit-limits-b lit-limits-e lit-type)
  1976. )
  1977. (error (list lit-limits-b lit-limits-e lit-type))))
  1978. ))))
  1979. (defun prolog-guess-fill-prefix ()
  1980. ;; fill 'txt entities?
  1981. (when (save-excursion
  1982. (end-of-line)
  1983. (nth 4 (syntax-ppss)))
  1984. (let* ((bounds (prolog-comment-limits))
  1985. (cbeg (car bounds))
  1986. (type (nth 2 bounds))
  1987. beg end)
  1988. (save-excursion
  1989. (end-of-line)
  1990. (setq end (point))
  1991. (beginning-of-line)
  1992. (setq beg (point))
  1993. (if (and (eq type 'line)
  1994. (> cbeg beg)
  1995. (save-excursion (not (search-forward-regexp "^[ \t]*%"
  1996. cbeg t))))
  1997. (progn
  1998. (goto-char cbeg)
  1999. (search-forward-regexp "%+[ \t]*" end t)
  2000. (prolog-replace-in-string (buffer-substring beg (point))
  2001. "[^ \t%]" " "))
  2002. ;(goto-char beg)
  2003. (if (search-forward-regexp "^[ \t]*\\(%+\\|\\*+\\|/\\*+\\)[ \t]*"
  2004. end t)
  2005. (prolog-replace-in-string (buffer-substring beg (point)) "/" " ")
  2006. (beginning-of-line)
  2007. (when (search-forward-regexp "^[ \t]+" end t)
  2008. (buffer-substring beg (point)))))))))
  2009. (defun prolog-fill-paragraph ()
  2010. "Fill paragraph comment at or after point."
  2011. (interactive)
  2012. (let* ((bounds (prolog-comment-limits))
  2013. (type (nth 2 bounds)))
  2014. (if (eq type 'line)
  2015. (let ((fill-prefix (prolog-guess-fill-prefix)))
  2016. (fill-paragraph nil))
  2017. (save-excursion
  2018. (save-restriction
  2019. ;; exclude surrounding lines that delimit a multiline comment
  2020. ;; and don't contain alphabetic characters, like "/*******",
  2021. ;; "- - - */" etc.
  2022. (save-excursion
  2023. (backward-paragraph)
  2024. (unless (bobp) (forward-line))
  2025. (if (string-match "^/\\*[^a-zA-Z]*$" (thing-at-point 'line))
  2026. (narrow-to-region (point-at-eol) (point-max))))
  2027. (save-excursion
  2028. (forward-paragraph)
  2029. (forward-line -1)
  2030. (if (string-match "^[^a-zA-Z]*\\*/$" (thing-at-point 'line))
  2031. (narrow-to-region (point-min) (point-at-bol))))
  2032. (let ((fill-prefix (prolog-guess-fill-prefix)))
  2033. (fill-paragraph nil))))
  2034. )))
  2035. (defun prolog-do-auto-fill ()
  2036. "Carry out Auto Fill for Prolog mode.
  2037. In effect it sets the `fill-prefix' when inside comments and then calls
  2038. `do-auto-fill'."
  2039. (let ((fill-prefix (prolog-guess-fill-prefix)))
  2040. (do-auto-fill)
  2041. ))
  2042. (defalias 'prolog-replace-in-string
  2043. (if (fboundp 'replace-in-string)
  2044. #'replace-in-string
  2045. (lambda (str regexp newtext &optional literal)
  2046. (replace-regexp-in-string regexp newtext str nil literal))))
  2047. ;;-------------------------------------------------------------------
  2048. ;; Online help
  2049. ;;-------------------------------------------------------------------
  2050. (defvar prolog-help-function
  2051. '((mercury nil)
  2052. (eclipse prolog-help-online)
  2053. ;; (sicstus prolog-help-info)
  2054. (sicstus prolog-find-documentation)
  2055. (swi prolog-help-online)
  2056. (t prolog-help-online))
  2057. "Alist for the name of the function for finding help on a predicate.")
  2058. (defun prolog-help-on-predicate ()
  2059. "Invoke online help on the atom under cursor."
  2060. (interactive)
  2061. (cond
  2062. ;; Redirect help for SICStus to `prolog-find-documentation'.
  2063. ((eq prolog-help-function-i 'prolog-find-documentation)
  2064. (prolog-find-documentation))
  2065. ;; Otherwise, ask for the predicate name and then call the function
  2066. ;; in prolog-help-function-i
  2067. (t
  2068. (let* ((word (prolog-atom-under-point))
  2069. (predicate (read-string
  2070. (format "Help on predicate%s: "
  2071. (if word
  2072. (concat " (default " word ")")
  2073. ""))
  2074. nil nil word))
  2075. ;;point
  2076. )
  2077. (if prolog-help-function-i
  2078. (funcall prolog-help-function-i predicate)
  2079. (error "Sorry, no help method defined for this Prolog system."))))
  2080. ))
  2081. (autoload 'Info-goto-node "info" nil t)
  2082. (declare-function Info-follow-nearest-node "info" (&optional FORK))
  2083. (defun prolog-help-info (predicate)
  2084. (let ((buffer (current-buffer))
  2085. oldp
  2086. (str (concat "^\\* " (regexp-quote predicate) " */")))
  2087. (pop-to-buffer nil)
  2088. (Info-goto-node prolog-info-predicate-index)
  2089. (if (not (re-search-forward str nil t))
  2090. (error "Help on predicate `%s' not found." predicate))
  2091. (setq oldp (point))
  2092. (if (re-search-forward str nil t)
  2093. ;; Multiple matches, ask user
  2094. (let ((max 2)
  2095. n)
  2096. ;; Count matches
  2097. (while (re-search-forward str nil t)
  2098. (setq max (1+ max)))
  2099. (goto-char oldp)
  2100. (re-search-backward "[^ /]" nil t)
  2101. (recenter 0)
  2102. (setq n (read-string ;; was read-input, which is obsolete
  2103. (format "Several matches, choose (1-%d): " max) "1"))
  2104. (forward-line (- (string-to-number n) 1)))
  2105. ;; Single match
  2106. (re-search-backward "[^ /]" nil t))
  2107. ;; (Info-follow-nearest-node (point))
  2108. (prolog-Info-follow-nearest-node)
  2109. (re-search-forward (concat "^`" (regexp-quote predicate)) nil t)
  2110. (beginning-of-line)
  2111. (recenter 0)
  2112. (pop-to-buffer buffer)))
  2113. (defun prolog-Info-follow-nearest-node ()
  2114. (if (featurep 'xemacs)
  2115. (Info-follow-nearest-node (point))
  2116. (Info-follow-nearest-node)))
  2117. (defun prolog-help-online (predicate)
  2118. (prolog-ensure-process)
  2119. (process-send-string "prolog" (concat "help(" predicate ").\n"))
  2120. (display-buffer "*prolog*"))
  2121. (defun prolog-help-apropos (string)
  2122. "Find Prolog apropos on given STRING.
  2123. This function is only available when `prolog-system' is set to `swi'."
  2124. (interactive "sApropos: ")
  2125. (cond
  2126. ((eq prolog-system 'swi)
  2127. (prolog-ensure-process)
  2128. (process-send-string "prolog" (concat "apropos(" string ").\n"))
  2129. (display-buffer "*prolog*"))
  2130. (t
  2131. (error "Sorry, no Prolog apropos available for this Prolog system."))))
  2132. (defun prolog-atom-under-point ()
  2133. "Return the atom under or left to the point."
  2134. (save-excursion
  2135. (let ((nonatom_chars "[](){},\. \t\n")
  2136. start)
  2137. (skip-chars-forward (concat "^" nonatom_chars))
  2138. (skip-chars-backward nonatom_chars)
  2139. (skip-chars-backward (concat "^" nonatom_chars))
  2140. (setq start (point))
  2141. (skip-chars-forward (concat "^" nonatom_chars))
  2142. (buffer-substring-no-properties start (point))
  2143. )))
  2144. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2145. ;; Help function with completion
  2146. ;; Stolen from Per Mildner's SICStus debugger mode and modified
  2147. (defun prolog-find-documentation ()
  2148. "Go to the Info node for a predicate in the SICStus Info manual."
  2149. (interactive)
  2150. (let ((pred (prolog-read-predicate)))
  2151. (prolog-goto-predicate-info pred)))
  2152. (defvar prolog-info-alist nil
  2153. "Alist with all builtin predicates.
  2154. Only for internal use by `prolog-find-documentation'")
  2155. ;; Very similar to prolog-help-info except that that function cannot
  2156. ;; cope with arity and that it asks the user if there are several
  2157. ;; functors with different arity. This function also uses
  2158. ;; prolog-info-alist for finding the info node, rather than parsing
  2159. ;; the predicate index.
  2160. (defun prolog-goto-predicate-info (predicate)
  2161. "Go to the info page for PREDICATE, which is a PredSpec."
  2162. (interactive)
  2163. (string-match "\\(.*\\)/\\([0-9]+\\).*$" predicate)
  2164. (let ((buffer (current-buffer))
  2165. (name (match-string 1 predicate))
  2166. (arity (string-to-number (match-string 2 predicate)))
  2167. ;oldp
  2168. ;(str (regexp-quote predicate))
  2169. )
  2170. (pop-to-buffer nil)
  2171. (Info-goto-node
  2172. prolog-info-predicate-index) ;; We must be in the SICStus pages
  2173. (Info-goto-node (car (cdr (assoc predicate prolog-info-alist))))
  2174. (prolog-find-term (regexp-quote name) arity "^`")
  2175. (recenter 0)
  2176. (pop-to-buffer buffer))
  2177. )
  2178. (defun prolog-read-predicate ()
  2179. "Read a PredSpec from the user.
  2180. Returned value is a string \"FUNCTOR/ARITY\".
  2181. Interaction supports completion."
  2182. (let ((default (prolog-atom-under-point)))
  2183. ;; If the predicate index is not yet built, do it now
  2184. (if (not prolog-info-alist)
  2185. (prolog-build-info-alist))
  2186. ;; Test if the default string could be the base for completion.
  2187. ;; Discard it if not.
  2188. (if (eq (try-completion default prolog-info-alist) nil)
  2189. (setq default nil))
  2190. ;; Read the PredSpec from the user
  2191. (completing-read
  2192. (if (zerop (length default))
  2193. "Help on predicate: "
  2194. (concat "Help on predicate (default " default "): "))
  2195. prolog-info-alist nil t nil nil default)))
  2196. (defun prolog-build-info-alist (&optional verbose)
  2197. "Build an alist of all builtins and library predicates.
  2198. Each element is of the form (\"NAME/ARITY\" . (INFO-NODE1 INFO-NODE2 ...)).
  2199. Typically there is just one Info node associated with each name
  2200. If an optional argument VERBOSE is non-nil, print messages at the beginning
  2201. and end of list building."
  2202. (if verbose
  2203. (message "Building info alist..."))
  2204. (setq prolog-info-alist
  2205. (let ((l ())
  2206. (last-entry (cons "" ())))
  2207. (save-excursion
  2208. (save-window-excursion
  2209. ;; select any window but the minibuffer (as we cannot switch
  2210. ;; buffers in minibuffer window.
  2211. ;; I am not sure this is the right/best way
  2212. (if (active-minibuffer-window) ; nil if none active
  2213. (select-window (next-window)))
  2214. ;; Do this after going away from minibuffer window
  2215. (save-window-excursion
  2216. (info))
  2217. (Info-goto-node prolog-info-predicate-index)
  2218. (goto-char (point-min))
  2219. (while (re-search-forward
  2220. "^\\* \\(.+\\)/\\([0-9]+\\)\\([^\n:*]*\\):" nil t)
  2221. (let* ((name (match-string 1))
  2222. (arity (string-to-number (match-string 2)))
  2223. (comment (match-string 3))
  2224. (fa (format "%s/%d%s" name arity comment))
  2225. info-node)
  2226. (beginning-of-line)
  2227. ;; Extract the info node name
  2228. (setq info-node (progn
  2229. (re-search-forward ":[ \t]*\\([^:]+\\).$")
  2230. (match-string 1)
  2231. ))
  2232. ;; ###### Easier? (from Milan version 0.1.28)
  2233. ;; (setq info-node (Info-extract-menu-node-name))
  2234. (if (equal fa (car last-entry))
  2235. (setcdr last-entry (cons info-node (cdr last-entry)))
  2236. (setq last-entry (cons fa (list info-node))
  2237. l (cons last-entry l)))))
  2238. (nreverse l)
  2239. ))))
  2240. (if verbose
  2241. (message "Building info alist... done.")))
  2242. ;;-------------------------------------------------------------------
  2243. ;; Miscellaneous functions
  2244. ;;-------------------------------------------------------------------
  2245. ;; For Windows. Change backslash to slash. SICStus handles either
  2246. ;; path separator but backslash must be doubled, therefore use slash.
  2247. (defun prolog-bsts (string)
  2248. "Change backslashes to slashes in STRING."
  2249. (let ((str1 (copy-sequence string))
  2250. (len (length string))
  2251. (i 0))
  2252. (while (< i len)
  2253. (if (char-equal (aref str1 i) ?\\)
  2254. (aset str1 i ?/))
  2255. (setq i (1+ i)))
  2256. str1))
  2257. ;;(defun prolog-temporary-file ()
  2258. ;; "Make temporary file name for compilation."
  2259. ;; (make-temp-name
  2260. ;; (concat
  2261. ;; (or
  2262. ;; (getenv "TMPDIR")
  2263. ;; (getenv "TEMP")
  2264. ;; (getenv "TMP")
  2265. ;; (getenv "SYSTEMP")
  2266. ;; "/tmp")
  2267. ;; "/prolcomp")))
  2268. ;;(setq prolog-temp-filename (prolog-bsts (prolog-temporary-file)))
  2269. (defun prolog-temporary-file ()
  2270. "Make temporary file name for compilation."
  2271. (if prolog-temporary-file-name
  2272. ;; We already have a file, erase content and continue
  2273. (progn
  2274. (write-region "" nil prolog-temporary-file-name nil 'silent)
  2275. prolog-temporary-file-name)
  2276. ;; Actually create the file and set `prolog-temporary-file-name'
  2277. ;; accordingly.
  2278. (setq prolog-temporary-file-name
  2279. (make-temp-file "prolcomp" nil ".pl"))))
  2280. (defun prolog-goto-prolog-process-buffer ()
  2281. "Switch to the prolog process buffer and go to its end."
  2282. (switch-to-buffer-other-window "*prolog*")
  2283. (goto-char (point-max))
  2284. )
  2285. (defun prolog-enable-sicstus-sd ()
  2286. "Enable the source level debugging facilities of SICStus 3.7 and later."
  2287. (interactive)
  2288. (require 'pltrace) ; Load the SICStus debugger code
  2289. ;; Turn on the source level debugging by default
  2290. (add-hook 'prolog-inferior-mode-hook 'pltrace-on)
  2291. (if (not prolog-use-sicstus-sd)
  2292. (progn
  2293. ;; If there is a *prolog* buffer, then call pltrace-on
  2294. (if (get-buffer "*prolog*")
  2295. ;; Avoid compilation warnings by using eval
  2296. (eval '(pltrace-on)))
  2297. (setq prolog-use-sicstus-sd t)
  2298. )))
  2299. (defun prolog-disable-sicstus-sd ()
  2300. "Disable the source level debugging facilities of SICStus 3.7 and later."
  2301. (interactive)
  2302. (setq prolog-use-sicstus-sd nil)
  2303. ;; Remove the hook
  2304. (remove-hook 'prolog-inferior-mode-hook 'pltrace-on)
  2305. ;; If there is a *prolog* buffer, then call pltrace-off
  2306. (if (get-buffer "*prolog*")
  2307. ;; Avoid compile warnings by using eval
  2308. (eval '(pltrace-off))))
  2309. (defun prolog-toggle-sicstus-sd ()
  2310. ;; FIXME: Use define-minor-mode.
  2311. "Toggle the source level debugging facilities of SICStus 3.7 and later."
  2312. (interactive)
  2313. (if prolog-use-sicstus-sd
  2314. (prolog-disable-sicstus-sd)
  2315. (prolog-enable-sicstus-sd)))
  2316. (defun prolog-debug-on (&optional arg)
  2317. "Enable debugging.
  2318. When called with prefix argument ARG, disable debugging instead."
  2319. (interactive "P")
  2320. (if arg
  2321. (prolog-debug-off)
  2322. (prolog-process-insert-string (get-process "prolog")
  2323. prolog-debug-on-string)
  2324. (process-send-string "prolog" prolog-debug-on-string)))
  2325. (defun prolog-debug-off ()
  2326. "Disable debugging."
  2327. (interactive)
  2328. (prolog-process-insert-string (get-process "prolog")
  2329. prolog-debug-off-string)
  2330. (process-send-string "prolog" prolog-debug-off-string))
  2331. (defun prolog-trace-on (&optional arg)
  2332. "Enable tracing.
  2333. When called with prefix argument ARG, disable tracing instead."
  2334. (interactive "P")
  2335. (if arg
  2336. (prolog-trace-off)
  2337. (prolog-process-insert-string (get-process "prolog")
  2338. prolog-trace-on-string)
  2339. (process-send-string "prolog" prolog-trace-on-string)))
  2340. (defun prolog-trace-off ()
  2341. "Disable tracing."
  2342. (interactive)
  2343. (prolog-process-insert-string (get-process "prolog")
  2344. prolog-trace-off-string)
  2345. (process-send-string "prolog" prolog-trace-off-string))
  2346. (defun prolog-zip-on (&optional arg)
  2347. "Enable zipping (for SICStus 3.7 and later).
  2348. When called with prefix argument ARG, disable zipping instead."
  2349. (interactive "P")
  2350. (if (not (and (eq prolog-system 'sicstus)
  2351. (prolog-atleast-version '(3 . 7))))
  2352. (error "Only works for SICStus 3.7 and later"))
  2353. (if arg
  2354. (prolog-zip-off)
  2355. (prolog-process-insert-string (get-process "prolog")
  2356. prolog-zip-on-string)
  2357. (process-send-string "prolog" prolog-zip-on-string)))
  2358. (defun prolog-zip-off ()
  2359. "Disable zipping (for SICStus 3.7 and later)."
  2360. (interactive)
  2361. (prolog-process-insert-string (get-process "prolog")
  2362. prolog-zip-off-string)
  2363. (process-send-string "prolog" prolog-zip-off-string))
  2364. ;; (defun prolog-create-predicate-index ()
  2365. ;; "Create an index for all predicates in the buffer."
  2366. ;; (let ((predlist '())
  2367. ;; clauseinfo
  2368. ;; object
  2369. ;; pos
  2370. ;; )
  2371. ;; (goto-char (point-min))
  2372. ;; ;; Replace with prolog-clause-start!
  2373. ;; (while (re-search-forward "^.+:-" nil t)
  2374. ;; (setq pos (match-beginning 0))
  2375. ;; (setq clauseinfo (prolog-clause-info))
  2376. ;; (setq object (prolog-in-object))
  2377. ;; (setq predlist (append
  2378. ;; predlist
  2379. ;; (list (cons
  2380. ;; (if (and (eq prolog-system 'sicstus)
  2381. ;; (prolog-in-object))
  2382. ;; (format "%s::%s/%d"
  2383. ;; object
  2384. ;; (nth 0 clauseinfo)
  2385. ;; (nth 1 clauseinfo))
  2386. ;; (format "%s/%d"
  2387. ;; (nth 0 clauseinfo)
  2388. ;; (nth 1 clauseinfo)))
  2389. ;; pos
  2390. ;; ))))
  2391. ;; (prolog-end-of-predicate))
  2392. ;; predlist))
  2393. (defun prolog-get-predspec ()
  2394. (save-excursion
  2395. (let ((state (prolog-clause-info))
  2396. (object (prolog-in-object)))
  2397. (if (or (equal (nth 0 state) "")
  2398. (nth 4 (syntax-ppss)))
  2399. nil
  2400. (if (and (eq prolog-system 'sicstus)
  2401. object)
  2402. (format "%s::%s/%d"
  2403. object
  2404. (nth 0 state)
  2405. (nth 1 state))
  2406. (format "%s/%d"
  2407. (nth 0 state)
  2408. (nth 1 state)))
  2409. ))))
  2410. ;; For backward compatibility. Stolen from custom.el.
  2411. (or (fboundp 'match-string)
  2412. ;; Introduced in Emacs 19.29.
  2413. (defun match-string (num &optional string)
  2414. "Return string of text matched by last search.
  2415. NUM specifies which parenthesized expression in the last regexp.
  2416. Value is nil if NUMth pair didn't match, or there were less than NUM pairs.
  2417. Zero means the entire text matched by the whole regexp or whole string.
  2418. STRING should be given if the last search was by `string-match' on STRING."
  2419. (if (match-beginning num)
  2420. (if string
  2421. (substring string (match-beginning num) (match-end num))
  2422. (buffer-substring (match-beginning num) (match-end num))))))
  2423. (defun prolog-pred-start ()
  2424. "Return the starting point of the first clause of the current predicate."
  2425. ;; FIXME: Use SMIE.
  2426. (save-excursion
  2427. (goto-char (prolog-clause-start))
  2428. ;; Find first clause, unless it was a directive
  2429. (if (and (not (looking-at "[:?]-"))
  2430. (not (looking-at "[ \t]*[%/]")) ; Comment
  2431. )
  2432. (let* ((pinfo (prolog-clause-info))
  2433. (predname (nth 0 pinfo))
  2434. (arity (nth 1 pinfo))
  2435. (op (point)))
  2436. (while (and (re-search-backward
  2437. (format "^%s\\([(\\.]\\| *%s\\)"
  2438. predname prolog-head-delimiter) nil t)
  2439. (= arity (nth 1 (prolog-clause-info)))
  2440. )
  2441. (setq op (point)))
  2442. (if (eq prolog-system 'mercury)
  2443. ;; Skip to the beginning of declarations of the predicate
  2444. (progn
  2445. (goto-char (prolog-beginning-of-clause))
  2446. (while (and (not (eq (point) op))
  2447. (looking-at
  2448. (format ":-[ \t]*\\(pred\\|mode\\)[ \t]+%s"
  2449. predname)))
  2450. (setq op (point))
  2451. (goto-char (prolog-beginning-of-clause)))))
  2452. op)
  2453. (point))))
  2454. (defun prolog-pred-end ()
  2455. "Return the position at the end of the last clause of the current predicate."
  2456. ;; FIXME: Use SMIE.
  2457. (save-excursion
  2458. (goto-char (prolog-clause-end)) ; If we are before the first predicate.
  2459. (goto-char (prolog-clause-start))
  2460. (let* ((pinfo (prolog-clause-info))
  2461. (predname (nth 0 pinfo))
  2462. (arity (nth 1 pinfo))
  2463. oldp
  2464. (notdone t)
  2465. (op (point)))
  2466. (if (looking-at "[:?]-")
  2467. ;; This was a directive
  2468. (progn
  2469. (if (and (eq prolog-system 'mercury)
  2470. (looking-at
  2471. (format ":-[ \t]*\\(pred\\|mode\\)[ \t]+\\(%s+\\)"
  2472. prolog-atom-regexp)))
  2473. ;; Skip predicate declarations
  2474. (progn
  2475. (setq predname (buffer-substring-no-properties
  2476. (match-beginning 2) (match-end 2)))
  2477. (while (re-search-forward
  2478. (format
  2479. "\n*\\(:-[ \t]*\\(pred\\|mode\\)[ \t]+\\)?%s[( \t]"
  2480. predname)
  2481. nil t))))
  2482. (goto-char (prolog-clause-end))
  2483. (setq op (point)))
  2484. ;; It was not a directive, find the last clause
  2485. (while (and notdone
  2486. (re-search-forward
  2487. (format "^%s\\([(\\.]\\| *%s\\)"
  2488. predname prolog-head-delimiter) nil t)
  2489. (= arity (nth 1 (prolog-clause-info))))
  2490. (setq oldp (point))
  2491. (setq op (prolog-clause-end))
  2492. (if (>= oldp op)
  2493. ;; End of clause not found.
  2494. (setq notdone nil)
  2495. ;; Continue while loop
  2496. (goto-char op))))
  2497. op)))
  2498. (defun prolog-clause-start (&optional not-allow-methods)
  2499. "Return the position at the start of the head of the current clause.
  2500. If NOTALLOWMETHODS is non-nil then do not match on methods in
  2501. objects (relevant only if `prolog-system' is set to `sicstus')."
  2502. (save-excursion
  2503. (let ((notdone t)
  2504. (retval (point-min)))
  2505. (end-of-line)
  2506. ;; SICStus object?
  2507. (if (and (not not-allow-methods)
  2508. (eq prolog-system 'sicstus)
  2509. (prolog-in-object))
  2510. (while (and
  2511. notdone
  2512. ;; Search for a head or a fact
  2513. (re-search-backward
  2514. ;; If in object, then find method start.
  2515. ;; "^[ \t]+[a-z$].*\\(:-\\|&\\|:: {\\|,\\)"
  2516. "^[ \t]+[a-z$].*\\(:-\\|&\\|:: {\\)" ; The comma causes
  2517. ; problems since we cannot assume
  2518. ; that the line starts at column 0,
  2519. ; thus we don't know if the line
  2520. ; is a head or a subgoal
  2521. (point-min) t))
  2522. (if (>= (prolog-paren-balance) 0) ; To no match on " a) :-"
  2523. ;; Start of method found
  2524. (progn
  2525. (setq retval (point))
  2526. (setq notdone nil)))
  2527. ) ; End of while
  2528. ;; Not in object
  2529. (while (and
  2530. notdone
  2531. ;; Search for a text at beginning of a line
  2532. ;; ######
  2533. ;; (re-search-backward "^[a-z$']" nil t))
  2534. (let ((case-fold-search nil))
  2535. (re-search-backward "^\\([[:lower:]$']\\|[:?]-\\)"
  2536. nil t)))
  2537. (let ((bal (prolog-paren-balance)))
  2538. (cond
  2539. ((> bal 0)
  2540. ;; Start of clause found
  2541. (progn
  2542. (setq retval (point))
  2543. (setq notdone nil)))
  2544. ((and (= bal 0)
  2545. (looking-at
  2546. (format ".*\\(\\.\\|%s\\|!,\\)[ \t]*\\(%%.*\\|\\)$"
  2547. prolog-head-delimiter)))
  2548. ;; Start of clause found if the line ends with a '.' or
  2549. ;; a prolog-head-delimiter
  2550. (progn
  2551. (setq retval (point))
  2552. (setq notdone nil))
  2553. )
  2554. (t nil) ; Do nothing
  2555. ))))
  2556. retval)))
  2557. (defun prolog-clause-end (&optional not-allow-methods)
  2558. "Return the position at the end of the current clause.
  2559. If NOTALLOWMETHODS is non-nil then do not match on methods in
  2560. objects (relevant only if `prolog-system' is set to `sicstus')."
  2561. (save-excursion
  2562. (beginning-of-line) ; Necessary since we use "^...." for the search.
  2563. (if (re-search-forward
  2564. (if (and (not not-allow-methods)
  2565. (eq prolog-system 'sicstus)
  2566. (prolog-in-object))
  2567. (format
  2568. "^\\(%s\\|%s\\|[^\n\'\"%%]\\)*&[ \t]*\\(\\|%%.*\\)$\\|[ \t]*}"
  2569. prolog-quoted-atom-regexp prolog-string-regexp)
  2570. (format
  2571. "^\\(%s\\|%s\\|[^\n\'\"%%]\\)*\\.[ \t]*\\(\\|%%.*\\)$"
  2572. prolog-quoted-atom-regexp prolog-string-regexp))
  2573. nil t)
  2574. (if (and (nth 8 (syntax-ppss))
  2575. (not (eobp)))
  2576. (progn
  2577. (forward-char)
  2578. (prolog-clause-end))
  2579. (point))
  2580. (point))))
  2581. (defun prolog-clause-info ()
  2582. "Return a (name arity) list for the current clause."
  2583. (save-excursion
  2584. (goto-char (prolog-clause-start))
  2585. (let* ((op (point))
  2586. (predname
  2587. (if (looking-at prolog-atom-char-regexp)
  2588. (progn
  2589. (skip-chars-forward "^ (\\.")
  2590. (buffer-substring op (point)))
  2591. ""))
  2592. (arity 0))
  2593. ;; Retrieve the arity.
  2594. (if (looking-at prolog-left-paren)
  2595. (let ((endp (save-excursion
  2596. (forward-list) (point))))
  2597. (setq arity 1)
  2598. (forward-char 1) ; Skip the opening paren.
  2599. (while (progn
  2600. (skip-chars-forward "^[({,'\"")
  2601. (< (point) endp))
  2602. (if (looking-at ",")
  2603. (progn
  2604. (setq arity (1+ arity))
  2605. (forward-char 1) ; Skip the comma.
  2606. )
  2607. ;; We found a string, list or something else we want
  2608. ;; to skip over.
  2609. (forward-sexp 1))
  2610. )))
  2611. (list predname arity))))
  2612. (defun prolog-in-object ()
  2613. "Return object name if the point is inside a SICStus object definition."
  2614. ;; Return object name if the last line that starts with a character
  2615. ;; that is neither white space nor a comment start
  2616. (save-excursion
  2617. (if (save-excursion
  2618. (beginning-of-line)
  2619. (looking-at "\\([^\n ]+\\)[ \t]*::[ \t]*{"))
  2620. ;; We were in the head of the object
  2621. (match-string 1)
  2622. ;; We were not in the head
  2623. (if (and (re-search-backward "^[a-z$'}]" nil t)
  2624. (looking-at "\\([^\n ]+\\)[ \t]*::[ \t]*{"))
  2625. (match-string 1)
  2626. nil))))
  2627. (defun prolog-beginning-of-clause ()
  2628. "Move to the beginning of current clause.
  2629. If already at the beginning of clause, move to previous clause."
  2630. (interactive)
  2631. (let ((point (point))
  2632. (new-point (prolog-clause-start)))
  2633. (if (and (>= new-point point)
  2634. (> point 1))
  2635. (progn
  2636. (goto-char (1- point))
  2637. (goto-char (prolog-clause-start)))
  2638. (goto-char new-point)
  2639. (skip-chars-forward " \t"))))
  2640. ;; (defun prolog-previous-clause ()
  2641. ;; "Move to the beginning of the previous clause."
  2642. ;; (interactive)
  2643. ;; (forward-char -1)
  2644. ;; (prolog-beginning-of-clause))
  2645. (defun prolog-end-of-clause ()
  2646. "Move to the end of clause.
  2647. If already at the end of clause, move to next clause."
  2648. (interactive)
  2649. (let ((point (point))
  2650. (new-point (prolog-clause-end)))
  2651. (if (and (<= new-point point)
  2652. (not (eq new-point (point-max))))
  2653. (progn
  2654. (goto-char (1+ point))
  2655. (goto-char (prolog-clause-end)))
  2656. (goto-char new-point))))
  2657. ;; (defun prolog-next-clause ()
  2658. ;; "Move to the beginning of the next clause."
  2659. ;; (interactive)
  2660. ;; (prolog-end-of-clause)
  2661. ;; (forward-char)
  2662. ;; (prolog-end-of-clause)
  2663. ;; (prolog-beginning-of-clause))
  2664. (defun prolog-beginning-of-predicate ()
  2665. "Go to the nearest beginning of predicate before current point.
  2666. Return the final point or nil if no such a beginning was found."
  2667. ;; FIXME: Hook into beginning-of-defun.
  2668. (interactive)
  2669. (let ((op (point))
  2670. (pos (prolog-pred-start)))
  2671. (if pos
  2672. (if (= op pos)
  2673. (if (not (bobp))
  2674. (progn
  2675. (goto-char pos)
  2676. (backward-char 1)
  2677. (setq pos (prolog-pred-start))
  2678. (if pos
  2679. (progn
  2680. (goto-char pos)
  2681. (point)))))
  2682. (goto-char pos)
  2683. (point)))))
  2684. (defun prolog-end-of-predicate ()
  2685. "Go to the end of the current predicate."
  2686. ;; FIXME: Hook into end-of-defun.
  2687. (interactive)
  2688. (let ((op (point)))
  2689. (goto-char (prolog-pred-end))
  2690. (if (= op (point))
  2691. (progn
  2692. (forward-line 1)
  2693. (prolog-end-of-predicate)))))
  2694. (defun prolog-insert-predspec ()
  2695. "Insert the predspec for the current predicate."
  2696. (interactive)
  2697. (let* ((pinfo (prolog-clause-info))
  2698. (predname (nth 0 pinfo))
  2699. (arity (nth 1 pinfo)))
  2700. (insert (format "%s/%d" predname arity))))
  2701. (defun prolog-view-predspec ()
  2702. "Insert the predspec for the current predicate."
  2703. (interactive)
  2704. (let* ((pinfo (prolog-clause-info))
  2705. (predname (nth 0 pinfo))
  2706. (arity (nth 1 pinfo)))
  2707. (message "%s/%d" predname arity)))
  2708. (defun prolog-insert-predicate-template ()
  2709. "Insert the template for the current clause."
  2710. (interactive)
  2711. (let* ((n 1)
  2712. oldp
  2713. (pinfo (prolog-clause-info))
  2714. (predname (nth 0 pinfo))
  2715. (arity (nth 1 pinfo)))
  2716. (insert predname)
  2717. (if (> arity 0)
  2718. (progn
  2719. (insert "(")
  2720. (when prolog-electric-dot-full-predicate-template
  2721. (setq oldp (point))
  2722. (while (< n arity)
  2723. (insert ",")
  2724. (setq n (1+ n)))
  2725. (insert ")")
  2726. (goto-char oldp))
  2727. ))
  2728. ))
  2729. (defun prolog-insert-next-clause ()
  2730. "Insert newline and the name of the current clause."
  2731. (interactive)
  2732. (insert "\n")
  2733. (prolog-insert-predicate-template))
  2734. (defun prolog-insert-module-modeline ()
  2735. "Insert a modeline for module specification.
  2736. This line should be first in the buffer.
  2737. The module name should be written manually just before the semi-colon."
  2738. (interactive)
  2739. (insert "%%% -*- Module: ; -*-\n")
  2740. (backward-char 6))
  2741. (defalias 'prolog-uncomment-region
  2742. (if (fboundp 'uncomment-region) #'uncomment-region
  2743. (lambda (beg end)
  2744. "Uncomment the region between BEG and END."
  2745. (interactive "r")
  2746. (comment-region beg end -1))))
  2747. (defun prolog-indent-predicate ()
  2748. "Indent the current predicate."
  2749. (interactive)
  2750. (indent-region (prolog-pred-start) (prolog-pred-end) nil))
  2751. (defun prolog-indent-buffer ()
  2752. "Indent the entire buffer."
  2753. (interactive)
  2754. (indent-region (point-min) (point-max) nil))
  2755. (defun prolog-mark-clause ()
  2756. "Put mark at the end of this clause and move point to the beginning."
  2757. (interactive)
  2758. (let ((pos (point)))
  2759. (goto-char (prolog-clause-end))
  2760. (forward-line 1)
  2761. (beginning-of-line)
  2762. (set-mark (point))
  2763. (goto-char pos)
  2764. (goto-char (prolog-clause-start))))
  2765. (defun prolog-mark-predicate ()
  2766. "Put mark at the end of this predicate and move point to the beginning."
  2767. (interactive)
  2768. (goto-char (prolog-pred-end))
  2769. (let ((pos (point)))
  2770. (forward-line 1)
  2771. (beginning-of-line)
  2772. (set-mark (point))
  2773. (goto-char pos)
  2774. (goto-char (prolog-pred-start))))
  2775. (defun prolog-electric--colon ()
  2776. "If `prolog-electric-colon-flag' is non-nil, insert the electric `:' construct.
  2777. That is, insert space (if appropriate), `:-' and newline if colon is pressed
  2778. at the end of a line that starts in the first column (i.e., clause heads)."
  2779. (when (and prolog-electric-colon-flag
  2780. (eq (char-before) ?:)
  2781. (not current-prefix-arg)
  2782. (eolp)
  2783. (not (memq (char-after (line-beginning-position))
  2784. '(?\s ?\t ?\%))))
  2785. (unless (memq (char-before (1- (point))) '(?\s ?\t))
  2786. (save-excursion (forward-char -1) (insert " ")))
  2787. (insert "-\n")
  2788. (indent-according-to-mode)))
  2789. (defun prolog-electric--dash ()
  2790. "If `prolog-electric-dash-flag' is non-nil, insert the electric `-' construct.
  2791. that is, insert space (if appropriate), `-->' and newline if dash is pressed
  2792. at the end of a line that starts in the first column (i.e., DCG heads)."
  2793. (when (and prolog-electric-dash-flag
  2794. (eq (char-before) ?-)
  2795. (not current-prefix-arg)
  2796. (eolp)
  2797. (not (memq (char-after (line-beginning-position))
  2798. '(?\s ?\t ?\%))))
  2799. (unless (memq (char-before (1- (point))) '(?\s ?\t))
  2800. (save-excursion (forward-char -1) (insert " ")))
  2801. (insert "->\n")
  2802. (indent-according-to-mode)))
  2803. (defun prolog-electric--dot ()
  2804. "Make dot electric, if `prolog-electric-dot-flag' is non-nil.
  2805. When invoked at the end of nonempty line, insert dot and newline.
  2806. When invoked at the end of an empty line, insert a recursive call to
  2807. the current predicate.
  2808. When invoked at the beginning of line, insert a head of a new clause
  2809. of the current predicate."
  2810. ;; Check for situations when the electricity should not be active
  2811. (if (or (not prolog-electric-dot-flag)
  2812. (not (eq (char-before) ?\.))
  2813. current-prefix-arg
  2814. (nth 8 (syntax-ppss))
  2815. ;; Do not be electric in a floating point number or an operator
  2816. (not
  2817. (save-excursion
  2818. (forward-char -1)
  2819. (skip-chars-backward " \t")
  2820. (let ((num (> (skip-chars-backward "0-9") 0)))
  2821. (or (bolp)
  2822. (memq (char-syntax (char-before))
  2823. (if num '(?w ?_) '(?\) ?w ?_)))))))
  2824. ;; Do not be electric if inside a parenthesis pair.
  2825. (not (= (car (syntax-ppss))
  2826. 0))
  2827. )
  2828. nil ;;Not electric.
  2829. (cond
  2830. ;; Beginning of line
  2831. ((save-excursion (forward-char -1) (bolp))
  2832. (delete-region (1- (point)) (point)) ;Delete the dot that called us.
  2833. (prolog-insert-predicate-template))
  2834. ;; At an empty line with at least one whitespace
  2835. ((save-excursion
  2836. (beginning-of-line)
  2837. (looking-at "[ \t]+\\.$"))
  2838. (delete-region (1- (point)) (point)) ;Delete the dot that called us.
  2839. (prolog-insert-predicate-template)
  2840. (when prolog-electric-dot-full-predicate-template
  2841. (save-excursion
  2842. (end-of-line)
  2843. (insert ".\n"))))
  2844. ;; Default
  2845. (t
  2846. (insert "\n"))
  2847. )))
  2848. (defun prolog-electric--underscore ()
  2849. "Replace variable with an underscore.
  2850. If `prolog-electric-underscore-flag' is non-nil and the point is
  2851. on a variable then replace the variable with underscore and skip
  2852. the following comma and whitespace, if any."
  2853. (when prolog-electric-underscore-flag
  2854. (let ((case-fold-search nil))
  2855. (when (and (not (nth 8 (syntax-ppss)))
  2856. (eq (char-before) ?_)
  2857. (save-excursion
  2858. (skip-chars-backward "[:alpha:]_")
  2859. (looking-at "\\_<[_[:upper:]][[:alnum:]_]*\\_>")))
  2860. (replace-match "_")
  2861. (skip-chars-forward ", \t\n")))))
  2862. (defun prolog-post-self-insert ()
  2863. (pcase last-command-event
  2864. (`?_ (prolog-electric--underscore))
  2865. (`?- (prolog-electric--dash))
  2866. (`?: (prolog-electric--colon))
  2867. ((or `?\( `?\; `?>) (prolog-electric--if-then-else))
  2868. (`?. (prolog-electric--dot))))
  2869. (defun prolog-find-term (functor arity &optional prefix)
  2870. "Go to the position at the start of the next occurrence of a term.
  2871. The term is specified with FUNCTOR and ARITY. The optional argument
  2872. PREFIX is the prefix of the search regexp."
  2873. (let* (;; If prefix is not set then use the default "\\<"
  2874. (prefix (if (not prefix)
  2875. "\\<"
  2876. prefix))
  2877. (regexp (concat prefix functor))
  2878. (i 1))
  2879. ;; Build regexp for the search if the arity is > 0
  2880. (if (= arity 0)
  2881. ;; Add that the functor must be at the end of a word. This
  2882. ;; does not work if the arity is > 0 since the closing )
  2883. ;; is not a word constituent.
  2884. (setq regexp (concat regexp "\\>"))
  2885. ;; Arity is > 0, add parens and commas
  2886. (setq regexp (concat regexp "("))
  2887. (while (< i arity)
  2888. (setq regexp (concat regexp ".+,"))
  2889. (setq i (1+ i)))
  2890. (setq regexp (concat regexp ".+)")))
  2891. ;; Search, and return position
  2892. (if (re-search-forward regexp nil t)
  2893. (goto-char (match-beginning 0))
  2894. (error "Term not found"))
  2895. ))
  2896. (defun prolog-variables-to-anonymous (beg end)
  2897. "Replace all variables within a region BEG to END by anonymous variables."
  2898. (interactive "r")
  2899. (save-excursion
  2900. (let ((case-fold-search nil))
  2901. (goto-char end)
  2902. (while (re-search-backward "\\<[A-Z_][a-zA-Z_0-9]*\\>" beg t)
  2903. (progn
  2904. (replace-match "_")
  2905. (backward-char)))
  2906. )))
  2907. ;;(defun prolog-regexp-dash-continuous-chars (chars)
  2908. ;; (let ((ints (mapcar #'prolog-char-to-int (string-to-list chars)))
  2909. ;; (beg 0)
  2910. ;; (end 0))
  2911. ;; (if (null ints)
  2912. ;; chars
  2913. ;; (while (and (< (+ beg 1) (length chars))
  2914. ;; (not (or (= (+ (nth beg ints) 1) (nth (+ beg 1) ints))
  2915. ;; (= (nth beg ints) (nth (+ beg 1) ints)))))
  2916. ;; (setq beg (+ beg 1)))
  2917. ;; (setq beg (+ beg 1)
  2918. ;; end beg)
  2919. ;; (while (and (< (+ end 1) (length chars))
  2920. ;; (or (= (+ (nth end ints) 1) (nth (+ end 1) ints))
  2921. ;; (= (nth end ints) (nth (+ end 1) ints))))
  2922. ;; (setq end (+ end 1)))
  2923. ;; (if (equal (substring chars end) "")
  2924. ;; (substring chars 0 beg)
  2925. ;; (concat (substring chars 0 beg) "-"
  2926. ;; (prolog-regexp-dash-continuous-chars (substring chars end))))
  2927. ;; )))
  2928. ;;(defun prolog-condense-character-sets (regexp)
  2929. ;; "Condense adjacent characters in character sets of REGEXP."
  2930. ;; (let ((next -1))
  2931. ;; (while (setq next (string-match "\\[\\(.*?\\)\\]" regexp (1+ next)))
  2932. ;; (setq regexp (replace-match (prolog-dash-letters (match-string 1 regexp))
  2933. ;; t t regexp 1))))
  2934. ;; regexp)
  2935. ;;-------------------------------------------------------------------
  2936. ;; Menu stuff (both for the editing buffer and for the inferior
  2937. ;; prolog buffer)
  2938. ;;-------------------------------------------------------------------
  2939. (unless (fboundp 'region-exists-p)
  2940. (defun region-exists-p ()
  2941. "Non-nil if the mark is set. Lobotomized version for Emacsen that do not provide their own."
  2942. (mark)))
  2943. ;; GNU Emacs ignores `easy-menu-add' so the order in which the menus
  2944. ;; are defined _is_ important!
  2945. (easy-menu-define
  2946. prolog-menu-help (list prolog-mode-map prolog-inferior-mode-map)
  2947. "Help menu for the Prolog mode."
  2948. ;; FIXME: Does it really deserve a whole menu to itself?
  2949. `(,(if (featurep 'xemacs) "Help"
  2950. ;; Not sure it's worth the trouble. --Stef
  2951. ;; (add-to-list 'menu-bar-final-items
  2952. ;; (easy-menu-intern "Prolog-Help"))
  2953. "Prolog-help")
  2954. ["On predicate" prolog-help-on-predicate prolog-help-function-i]
  2955. ["Apropos" prolog-help-apropos (eq prolog-system 'swi)]
  2956. "---"
  2957. ["Describe mode" describe-mode t]))
  2958. (easy-menu-define
  2959. prolog-edit-menu-runtime prolog-mode-map
  2960. "Runtime Prolog commands available from the editing buffer"
  2961. ;; FIXME: Don't use a whole menu for just "Run Mercury". --Stef
  2962. `("System"
  2963. ;; Runtime menu name.
  2964. ,@(unless (featurep 'xemacs)
  2965. '(:label (cond ((eq prolog-system 'eclipse) "ECLiPSe")
  2966. ((eq prolog-system 'mercury) "Mercury")
  2967. (t "System"))))
  2968. ;; Consult items, NIL for mercury.
  2969. ["Consult file" prolog-consult-file
  2970. :included (not (eq prolog-system 'mercury))]
  2971. ["Consult buffer" prolog-consult-buffer
  2972. :included (not (eq prolog-system 'mercury))]
  2973. ["Consult region" prolog-consult-region :active (region-exists-p)
  2974. :included (not (eq prolog-system 'mercury))]
  2975. ["Consult predicate" prolog-consult-predicate
  2976. :included (not (eq prolog-system 'mercury))]
  2977. ;; Compile items, NIL for everything but SICSTUS.
  2978. ,(if (featurep 'xemacs) "---"
  2979. ["---" nil :included (eq prolog-system 'sicstus)])
  2980. ["Compile file" prolog-compile-file
  2981. :included (eq prolog-system 'sicstus)]
  2982. ["Compile buffer" prolog-compile-buffer
  2983. :included (eq prolog-system 'sicstus)]
  2984. ["Compile region" prolog-compile-region :active (region-exists-p)
  2985. :included (eq prolog-system 'sicstus)]
  2986. ["Compile predicate" prolog-compile-predicate
  2987. :included (eq prolog-system 'sicstus)]
  2988. ;; Debug items, NIL for Mercury.
  2989. ,(if (featurep 'xemacs) "---"
  2990. ["---" nil :included (not (eq prolog-system 'mercury))])
  2991. ;; FIXME: Could we use toggle or radio buttons? --Stef
  2992. ["Debug" prolog-debug-on :included (not (eq prolog-system 'mercury))]
  2993. ["Debug off" prolog-debug-off
  2994. ;; In SICStus, these are pairwise disjunctive,
  2995. ;; so it's enough with a single "off"-command
  2996. :included (not (memq prolog-system '(mercury sicstus)))]
  2997. ["Trace" prolog-trace-on :included (not (eq prolog-system 'mercury))]
  2998. ["Trace off" prolog-trace-off
  2999. :included (not (memq prolog-system '(mercury sicstus)))]
  3000. ["Zip" prolog-zip-on :included (and (eq prolog-system 'sicstus)
  3001. (prolog-atleast-version '(3 . 7)))]
  3002. ["All debug off" prolog-debug-off
  3003. :included (eq prolog-system 'sicstus)]
  3004. ["Source level debugging"
  3005. prolog-toggle-sicstus-sd
  3006. :included (and (eq prolog-system 'sicstus)
  3007. (prolog-atleast-version '(3 . 7)))
  3008. :style toggle
  3009. :selected prolog-use-sicstus-sd]
  3010. "---"
  3011. ["Run" run-prolog
  3012. :suffix (cond ((eq prolog-system 'eclipse) "ECLiPSe")
  3013. ((eq prolog-system 'mercury) "Mercury")
  3014. (t "Prolog"))]))
  3015. (easy-menu-define
  3016. prolog-edit-menu-insert-move prolog-mode-map
  3017. "Commands for Prolog code manipulation."
  3018. '("Prolog"
  3019. ["Comment region" comment-region (region-exists-p)]
  3020. ["Uncomment region" prolog-uncomment-region (region-exists-p)]
  3021. ["Add comment/move to comment" indent-for-comment t]
  3022. ["Convert variables in region to '_'" prolog-variables-to-anonymous
  3023. :active (region-exists-p) :included (not (eq prolog-system 'mercury))]
  3024. "---"
  3025. ["Insert predicate template" prolog-insert-predicate-template t]
  3026. ["Insert next clause head" prolog-insert-next-clause t]
  3027. ["Insert predicate spec" prolog-insert-predspec t]
  3028. ["Insert module modeline" prolog-insert-module-modeline t]
  3029. "---"
  3030. ["Beginning of clause" prolog-beginning-of-clause t]
  3031. ["End of clause" prolog-end-of-clause t]
  3032. ["Beginning of predicate" prolog-beginning-of-predicate t]
  3033. ["End of predicate" prolog-end-of-predicate t]
  3034. "---"
  3035. ["Indent line" indent-according-to-mode t]
  3036. ["Indent region" indent-region (region-exists-p)]
  3037. ["Indent predicate" prolog-indent-predicate t]
  3038. ["Indent buffer" prolog-indent-buffer t]
  3039. ["Align region" align (region-exists-p)]
  3040. "---"
  3041. ["Mark clause" prolog-mark-clause t]
  3042. ["Mark predicate" prolog-mark-predicate t]
  3043. ["Mark paragraph" mark-paragraph t]
  3044. ))
  3045. (defun prolog-menu ()
  3046. "Add the menus for the Prolog editing buffers."
  3047. (easy-menu-add prolog-edit-menu-insert-move)
  3048. (easy-menu-add prolog-edit-menu-runtime)
  3049. ;; Add predicate index menu
  3050. (setq-local imenu-create-index-function
  3051. 'imenu-default-create-index-function)
  3052. ;;Milan (this has problems with object methods...) ###### Does it? (Stefan)
  3053. (setq-local imenu-prev-index-position-function
  3054. #'prolog-beginning-of-predicate)
  3055. (setq-local imenu-extract-index-name-function #'prolog-get-predspec)
  3056. (if (and prolog-imenu-flag
  3057. (< (count-lines (point-min) (point-max)) prolog-imenu-max-lines))
  3058. (imenu-add-to-menubar "Predicates"))
  3059. (easy-menu-add prolog-menu-help))
  3060. (easy-menu-define
  3061. prolog-inferior-menu-all prolog-inferior-mode-map
  3062. "Menu for the inferior Prolog buffer."
  3063. `("Prolog"
  3064. ;; Runtime menu name.
  3065. ,@(unless (featurep 'xemacs)
  3066. '(:label (cond ((eq prolog-system 'eclipse) "ECLiPSe")
  3067. ((eq prolog-system 'mercury) "Mercury")
  3068. (t "Prolog"))))
  3069. ;; Debug items, NIL for Mercury.
  3070. ,(if (featurep 'xemacs) "---"
  3071. ["---" nil :included (not (eq prolog-system 'mercury))])
  3072. ;; FIXME: Could we use toggle or radio buttons? --Stef
  3073. ["Debug" prolog-debug-on :included (not (eq prolog-system 'mercury))]
  3074. ["Debug off" prolog-debug-off
  3075. ;; In SICStus, these are pairwise disjunctive,
  3076. ;; so it's enough with a single "off"-command
  3077. :included (not (memq prolog-system '(mercury sicstus)))]
  3078. ["Trace" prolog-trace-on :included (not (eq prolog-system 'mercury))]
  3079. ["Trace off" prolog-trace-off
  3080. :included (not (memq prolog-system '(mercury sicstus)))]
  3081. ["Zip" prolog-zip-on :included (and (eq prolog-system 'sicstus)
  3082. (prolog-atleast-version '(3 . 7)))]
  3083. ["All debug off" prolog-debug-off
  3084. :included (eq prolog-system 'sicstus)]
  3085. ["Source level debugging"
  3086. prolog-toggle-sicstus-sd
  3087. :included (and (eq prolog-system 'sicstus)
  3088. (prolog-atleast-version '(3 . 7)))
  3089. :style toggle
  3090. :selected prolog-use-sicstus-sd]
  3091. ;; Runtime.
  3092. "---"
  3093. ["Interrupt Prolog" comint-interrupt-subjob t]
  3094. ["Quit Prolog" comint-quit-subjob t]
  3095. ["Kill Prolog" comint-kill-subjob t]))
  3096. (defun prolog-inferior-menu ()
  3097. "Create the menus for the Prolog inferior buffer.
  3098. This menu is dynamically created because one may change systems during
  3099. the life of an Emacs session."
  3100. (easy-menu-add prolog-inferior-menu-all)
  3101. (easy-menu-add prolog-menu-help))
  3102. (defun prolog-mode-version ()
  3103. "Echo the current version of Prolog mode in the minibuffer."
  3104. (interactive)
  3105. (message "Using Prolog mode version %s" prolog-mode-version))
  3106. (provide 'prolog)
  3107. ;;; prolog.el ends here