home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / p / plbin.zip / pl / lisp / qprolog-mode.el < prev    next >
Lisp/Scheme  |  1992-05-26  |  17KB  |  518 lines

  1. ;;;  SCCS: @(#)91/01/11 qprolog-mode.el    3.9
  2. ;;;            Quintus Prolog - GNU Emacs Interface
  3. ;;;                         Support Functions
  4. ;;;
  5. ;;;                Consolidated by Sitaram Muralidhar
  6. ;;;
  7. ;;;                   sitaram@quintus.com
  8. ;;;              Quintus Computer Systems, Inc.
  9. ;;;                  2 May 1989       
  10. ;;;
  11. ;;; This file defines functions that support the Quintus Prolog - GNU Emacs
  12. ;;; interface.
  13. ;;;
  14. ;;;                   Acknowledgements
  15. ;;;
  16. ;;;
  17. ;;; This interface was made possible by contributions from Fernando
  18. ;;; Pereira and various customers of Quintus Computer Systems, Inc.,
  19. ;;; based on code for Quintus's Unipress Emacs interface. 
  20. ;;; 
  21.  
  22. ;;;
  23. ;;;  qprequire - suppresses message printing but offers the same
  24. ;;;  functionality as require.
  25. ;;;
  26.  
  27. ;;;  This file is slightly modified version for proper cooperation with
  28. ;;;  SWI-Prolog:
  29. ;;;
  30. ;;;    * Prompt has changed
  31. ;;;    * The keybindings for 'prolog-compile are left out as this does    
  32. ;;;      not yet work
  33. ;;;    * prolog-mode runs the 'prolog-mode-hook
  34. ;;;    * run-prolog runs the 'inferior-prolog-mode-hook
  35.  
  36.  
  37. (cond ((null (car global-mode-string))
  38.        (setq global-mode-string (list ""))))
  39. (defvar original-mode-string global-mode-string
  40.   "The default mode line string when prolog starts up. Note that if the
  41. mode string is changed after prolog is invoked the new setting will be lost")
  42.  
  43. (defun qprequire (file)
  44.   (cond ((not (featurep file))
  45.      (load (prin1-to-string file) nil t))
  46.     (t t))
  47. )
  48.  
  49. (defvar prolog-prompt-pattern "^| \\?- " ; SWI
  50.   "Regexp to detect prompt (toplevel)")
  51.  
  52. (defvar prolog-zap-file (make-temp-name "/tmp/qp")
  53.   "Temporary file name used for code being consulted or compiled in Prolog.")
  54.  
  55. (defvar prolog-goal-history nil
  56.   "List of recent goals executed by Quintus prolog.")
  57.  
  58. (defvar multiline-goal nil
  59.   "Multiline goal executed by Quintus prolog.")
  60.  
  61. (defvar prolog-mode-syntax-table nil
  62.   "Syntax table used while in prolog mode.")
  63.  
  64. (defvar prolog-mode-abbrev-table nil "")
  65.  
  66. (defvar quintus-gnu-version "18.55/3.1" 
  67.  " Version numbers of this version of Quintus-GNU emacs interface.")
  68.  
  69. (define-abbrev-table 'prolog-mode-abbrev-table ())
  70.  
  71. (defvar prolog-mode-map nil)
  72. (qprequire 'quintaux)
  73. (if prolog-mode-map 
  74.     nil
  75.   (setq prolog-mode-map (make-sparse-keymap))
  76.   (define-key prolog-mode-map "\t"     'prolog-indent-line       )
  77.   (define-key prolog-mode-map "\e\C-q" 'prolog-indent-clause     )
  78.   (define-key prolog-mode-map "\e\C-a" 'beginning-of-clause      )
  79.   (define-key prolog-mode-map "\eh"    'mark-clause              )
  80.   (define-key prolog-mode-map "\ef"    'forward-prolog-word      )
  81.   (define-key prolog-mode-map "\eb"    'backward-prolog-word     )
  82.   (define-key prolog-mode-map "\e\C-f" 'forward-term             )
  83.   (define-key prolog-mode-map "\e\C-b" 'backward-term            )
  84.   (define-key prolog-mode-map "\ed"    'kill-prolog-word         )
  85.   (define-key prolog-mode-map "\e\177" 'backward-kill-prolog-word)
  86.   (define-key prolog-mode-map "\e\C-k" 'kill-clause              )
  87.   (define-key prolog-mode-map "\e\C-e" 'end-of-clause            )
  88.   (define-key prolog-mode-map "\e."    'find-definition          )
  89.   (define-key prolog-mode-map "\e,"    'find-more-definition     )
  90. ; (define-key prolog-mode-map "\e\C-x" 'prolog-consult-predicate ) ;SWI
  91. ; (define-key prolog-mode-map "\ek"    'prolog-compile           ) ;SWI
  92. ; (define-key prolog-mode-map "\ei"    'prolog-compile           ) ;SWI
  93.   (define-key prolog-mode-map "\e#"    'shell-filename-complete  )
  94. )
  95.  
  96. (fset 'prolog-mode 'prolog-mode) 
  97.  
  98. (defun quintus-version ()
  99.   (interactive)
  100.   (message "Quintus-Gnu Emacs interface version %s" 
  101.        quintus-gnu-version)
  102. )
  103.   
  104.  
  105. (defun prolog-mode ()
  106.   "Major mode for editing files of prolog code.
  107.  The following commands are available:
  108.  \\{prolog-mode-map}."
  109.  
  110.   (interactive)
  111.   (kill-all-local-variables)
  112.   (use-local-map prolog-mode-map)
  113.   (setq mode-name "prolog")
  114.   (setq major-mode 'prolog-mode)
  115.   (setq local-abbrev-table prolog-mode-abbrev-table)
  116.   (or (mark) (set-mark 0))
  117.   (ensure-prolog-syntax)
  118.   (prolog-mode-variables)
  119.   (run-hooks 'prolog-mode-hook))    ; SWI
  120.  
  121. (defun ensure-prolog-syntax ()
  122.   "Hack to make sure Prolog syntax table is set up properly"
  123.   ; PMartin 18 Mar 88
  124.   (if (null prolog-mode-syntax-table)
  125.       (progn
  126.     (setq prolog-mode-syntax-table (make-syntax-table))
  127.     (set-syntax-table prolog-mode-syntax-table)
  128.     (modify-syntax-entry ?\( "()  ")
  129.     (modify-syntax-entry ?\) ")(  ")
  130.     (modify-syntax-entry ?\{ "(}  ")
  131.     (modify-syntax-entry ?\} "){  ")
  132.     (modify-syntax-entry ?\[ "(]  ")
  133.     (modify-syntax-entry ?\] ")[  ")
  134.     (modify-syntax-entry ?\_ "_   ")
  135.     (modify-syntax-entry ?\% "<   ")
  136.     (modify-syntax-entry ?\n ">   ")
  137.     (modify-syntax-entry ?\" "\"  ")
  138.     (modify-syntax-entry ?\\ "\\  ")
  139.     (modify-syntax-entry ?/ "  14")
  140.     (modify-syntax-entry ?* "  23")
  141.     (modify-syntax-entry ?' "w   "))
  142.     ))
  143.  
  144. (defun prolog-mode-commands (map)
  145.   (define-key map "\C-m" 'prolog-newline)
  146.   (define-key map "\e\C-y" 'command-pop)
  147.   (define-key map "\e\C-f" 'forward-term)
  148.   (define-key map "\e\C-b" 'backward-term)
  149.   (define-key map "\e." 'find-definition)
  150.   (define-key map "\e," 'find-more-definition)
  151.   (define-key map "\ex" 'meta-x-trap)
  152.   (define-key shell-mode-map "\C-c\C-c" 'interrupt-prolog)
  153.   (define-key map "\C-x\C-e" 'goal-history)
  154.   (define-key map "\C-x\C-y" 'repeat-matching-goal-command)
  155.   (define-key map "\C-d"  'qp-kill-character)
  156.   (define-key map "\ed"   'qp-kill-word)
  157.   (define-key map "\eD"   'qp-kill-word)
  158.   (define-key map "\e\177"  'qp-backward-kill-word)
  159.   (define-key map "\C-c\C-w"  'qp-backward-kill-word)
  160.   (define-key map "\C-x\177"  'qp-backward-kill-sentence)
  161.   (define-key map "\ek"  'qp-kill-sentence)
  162.   (define-key map "\177"  'qp-backward-kill-character)
  163.   (define-key map "\C-k"  'qp-kill-lines)
  164.   (define-key map "\C-w"  'qp-kill-region))
  165.  
  166. (defun prolog-mode-variables ()
  167.   (set-syntax-table prolog-mode-syntax-table)
  168.   (setq local-abbrev-table prolog-mode-abbrev-table)
  169.   (make-local-variable 'paragraph-start)
  170.   (setq paragraph-start (concat "^$\\|" page-delimiter))
  171.   (make-local-variable 'paragraph-separate)
  172.   (setq paragraph-separate paragraph-start)
  173.   (make-local-variable 'indent-line-function)
  174.   (setq indent-line-function 'prolog-indent-line)
  175.   (make-local-variable 'comment-start)
  176.   (setq comment-start "%")
  177.   (make-local-variable 'comment-start-skip)
  178.   (setq comment-start-skip "%+ *")
  179.   (make-local-variable 'comment-column)
  180.   (setq comment-column 50)
  181.   (make-local-variable 'comment-indent-hook)
  182.   (setq comment-indent-hook 'prolog-comment-indent))
  183.  
  184. (defvar inferior-prolog-mode-map nil)
  185.  
  186. (qprequire 'shell)
  187. (qprequire 'qpshell-command-ring)
  188.  
  189. (if inferior-prolog-mode-map
  190.     nil
  191.   (setq inferior-prolog-mode-map (copy-alist shell-mode-map))
  192.   (prolog-mode-commands inferior-prolog-mode-map))
  193.  
  194.  
  195. (defun inferior-prolog-mode ()
  196.     "Major mode for interacting with an inferior Prolog process.
  197.  
  198. The following commands are available:
  199. \\{inferior-prolog-mode-map}
  200.  
  201. Entry to this mode calls the value of prolog-mode-hook with no arguments,
  202. if that value is non-nil.  Likewise with the value of shell-mode-hook.
  203. prolog-mode-hook is called after shell-mode-hook.
  204.  
  205. You can send text to the inferior Prolog from other buffers
  206. using the commands send-region, send-string.
  207.  
  208. Commands:
  209. Delete converts tabs to spaces as it moves back.
  210. Tab indents for Prolog; with argument, shifts rest
  211.  of expression rigidly with the current line.
  212. Meta-Control-Q does Tab on each line starting within following expression.
  213. Paragraphs are separated only by blank lines.  Percent(%) start comments.
  214.  
  215. Return at end of buffer sends line as input.
  216. Return not at end copies rest of line to end and sends it.
  217. C-d at end of buffer sends end-of-file as input.
  218. C-d not at end or with arg deletes or kills characters.
  219. C-u and C-w are kill commands, imitating normal Unix input editing.
  220. C-c interrupts the shell or its current subjob if any.
  221. C-z stops, likewise.  C-\\ sends quit signal, likewise.
  222.  
  223. C-x C-k deletes last batch of output from shell.
  224. C-x C-v puts top of last batch of output at top of window."
  225.     (interactive)
  226.     (kill-all-local-variables)
  227.     (setq major-mode 'inferior-prolog-mode)
  228.     (setq mode-name "Prolog")
  229.     (setq mode-line-format 
  230.           "--%1*%1*-Emacs: %12b   %M          %[(%m: %s)%]----%3p--%-")
  231.     (prolog-mode-variables)
  232.     (use-local-map inferior-prolog-mode-map)
  233.     (make-local-variable 'last-input-start)
  234.     (setq last-input-start (make-marker))
  235.     (make-local-variable 'last-input-end)
  236.     (setq last-input-end (make-marker))
  237.     (make-local-variable '@at-debugger-prompt)
  238.     (setq  @at-debugger-prompt nil)
  239.     (run-hooks 'shell-mode-hook 'inferior-prolog-mode-hook)) ; SWI
  240.  
  241. (defvar startup-jcl (concat " +C" " Emacs:" prolog-zap-file)
  242.   "String that identifies that emacs is the sender")
  243. (defvar *prolog-executable* nil
  244.   "The prolog executable")
  245. (defvar *prolog-flags* nil
  246.   "Prolog command line switches")
  247.  
  248. (defun run-prolog (&optional gnu-context)
  249.     "Run an inferior Prolog process, input and output via buffer
  250. *prolog*.  Environment variable QUINTUS_PROLOG_PATH must be set to the
  251. pathname of the prolog executable before invoking this function
  252. interactively. Optional first argument means fire up named save-state;
  253. Called by GNU Emacs 'recover-context'. Gnu-context is the name of the
  254. prolog saved-state."
  255.     (interactive)
  256.     (ensure-prolog-syntax)
  257.     (qprequire 'shell)
  258.     (cond (gnu-context
  259.        (setq *prolog-executable* gnu-context))
  260.       (t (if (getenv "QUINTUS_PROLOG_PATH")
  261.          (let  
  262.              ((prolog-command-string (concat 
  263.                            (getenv "QUINTUS_PROLOG_PATH")
  264.                            startup-jcl)))
  265.            (get-prolog-exec-and-flags prolog-command-string))
  266.            (setq *prolog-executable* "")))
  267.     )
  268.     (cond ((string-equal *prolog-executable* "")
  269.        (message "Environment variable QUINTUS_PROLOG_PATH not set"))
  270.       (t (switch-to-buffer  (apply 'make-shell "prolog"
  271.                        *prolog-executable* nil  
  272.                     *prolog-flags*))
  273.          (set-process-filter (get-process "prolog") 'prolog-process-filter)
  274.          (sleep-for 2)
  275.          (inferior-prolog-mode)
  276.          (error-occurred (prolog-startup-hook))
  277.       )
  278.     )
  279. )
  280.  
  281. ;---------------------------------------------------------------------
  282. ; Separates the executable from rest of args (to prolog)
  283. ;---------------------------------------------------------------------
  284. (defun get-prolog-exec-and-flags (prolog-command-string)
  285.   (let ((i 1))
  286.     (while (not (string-equal 
  287.           (substring prolog-command-string i (+ i 1))
  288.           " "))
  289.       (setq i (+ i 1)))
  290.     (setq *prolog-executable* (substring prolog-command-string 0 i))
  291.     (setq *prolog-flags* (prolog-args (substring prolog-command-string
  292.                          (+ i 1))))
  293.   )
  294. )
  295. ;---------------------------------------------------------------------
  296. ; Breaks up a single string of args into individual strings
  297. ;---------------------------------------------------------------------
  298. (defun prolog-args (prolog-command-string)
  299.   (let ((argnum 1)
  300.     (arg-list nil)
  301.     (done t))
  302.     (while done
  303.       (cond ((not (string-equal (setq arg
  304.                       (get-arg prolog-command-string argnum))
  305.                 "")
  306.          )
  307.          (set-variable (intern (concat "arg" "_" argnum)) arg)
  308.          (setq arg-list (cons arg arg-list))
  309.          (setq argnum (+ argnum 1)))
  310.         (t (setq done nil))
  311.       )
  312.     )
  313.   (nreverse arg-list)
  314.   )
  315. )
  316.  
  317. ; ----------------------------------------------------------------------
  318. ; get-arg returns the arg-pos'th command string from prolog-command-string
  319. ; ---------------------------------------------------------------------- 
  320. (defun get-arg (prolog-command-string arg-pos)
  321.   (let ((i 0)
  322.     (j 0)
  323.     (done t)
  324.     (arg arg-pos)
  325.     (len (length prolog-command-string)))
  326.     (while (and (/= arg 0)
  327.          done)
  328.       (while (and (< i len)
  329.           (string-equal (substring prolog-command-string i (+ i 1))
  330.                 " "))
  331.     (setq i (+ i 1))
  332.     (setq j (+ j 1))
  333.       )
  334.       (while (and (< i len)
  335.           (not (string-equal 
  336.              (substring prolog-command-string i (+ i 1))
  337.              " ")
  338.           )
  339.          )
  340.     (setq i (+ i 1))
  341.       )
  342.       (cond ((>= i len)
  343.          (setq done nil))
  344.       )
  345.       (setq arg (1- arg))
  346.       (cond ((/= arg 0)
  347.           (setq j i))
  348.       )
  349.     )
  350.     (substring prolog-command-string j i)
  351.   )
  352. )
  353.     
  354.  
  355. (defmacro prolog-in-other-window ()
  356.   (if (equal (get-lru-window) (selected-window))
  357.       (split-window-vertically nil))
  358.   (pop-to-buffer "*prolog*"))
  359.  
  360. ;;
  361. ;;
  362. ; This function no longer used, see prolog-newline (qprocess.el) instead
  363. ;;
  364. ;;
  365. (defun send-to-prolog ()
  366.   "Send input to subshell.
  367. At end of buffer, sends all text after last output
  368.  as input to the subshell, including a newline inserted at the end.
  369. Not at end, copies current line to the end of the buffer and sends it,
  370. after first attempting to discard any prompt at the beginning of the line
  371. by matching the regexp that is the value of shell-prompt-pattern if possible.
  372. This regexp should start with \"^\"."
  373.   (interactive)
  374.   (end-of-line)
  375.   (cond ((or (null *prolog-term-reading-mode*)
  376.          (clause-end-p))
  377.   (if (eobp) 
  378.       (progn
  379.         (move-marker last-input-start
  380.                      (process-mark (get-buffer-process (current-buffer))))
  381.         (insert ?\n)
  382.         (move-marker last-input-end (point)))
  383.     (beginning-of-line)
  384.     (re-search-forward prolog-prompt-pattern nil t)
  385.     (let ((copy (buffer-substring (point)
  386.                   (progn (end-of-clause 1) 
  387.                                          (point)))))
  388.       (goto-char (point-max))
  389.       (move-marker last-input-start (point))
  390.       (insert copy)
  391.       (insert ?\n))
  392.     (move-marker last-input-end (point)))
  393.   (check-for-module-change last-input-start last-input-end)
  394.   (save-command-in-ring last-input-start last-input-end)
  395. ;;
  396. ;; The following "cond" has been added to facilitate goal-history
  397. ;; functionality. Nothing is added to goal-history if at debugger
  398. ;; prompt. The variable multiline goal keeps track of multi-line
  399. ;; queries. This is required since each line is sent to prolog 
  400. ;; separately. The variable is reset when the query is complete.
  401. ;;
  402.   (cond ((null @at-debugger-prompt)
  403.      (save-excursion
  404.         (goto-char last-input-start)
  405.         (cond (( string-equal (setq current-goal (valid-line)) "")
  406.            (setq multiline-goal (concat multiline-goal
  407.                         (buffer-substring
  408.                           last-input-start
  409.                           (1- last-input-end)))))
  410.           ((not (null multiline-goal))
  411.            (setq multiline-goal (concat multiline-goal 
  412.                         current-goal))
  413.            (setq prolog-goal-history
  414.              (cons multiline-goal prolog-goal-history))
  415.            (setq multiline-goal nil))
  416.           (t (setq prolog-goal-history 
  417.                (cons current-goal prolog-goal-history))))))
  418.    )
  419.   (setq *prolog-term-reading-mode* nil)
  420.   (setq @at-debugger-prompt nil)
  421.   (let ((process (get-buffer-process (current-buffer))))
  422.     (send-region process last-input-start last-input-end)
  423.     (set-marker (process-mark process) (point))))))
  424.  
  425. (defun small-prolog-window ()
  426.   (interactive)
  427.     (cond
  428.      ((get-buffer-window "*prolog*")
  429.       (expand-window (- (screen-height) window-min-height)))
  430.      (t (split-window-vertically (- (window-height) window-min-height))
  431.         (other-window 1)
  432.         (switch-to-buffer "*prolog*"))))
  433.  
  434. (defun big-prolog-window ()
  435.   (interactive)
  436.     (cond
  437.      ((get-buffer-window "*prolog*")
  438.       (expand-window (- (screen-height) window-min-height)))
  439.      (t (split-window-vertically (- (window-height) window-min-height))
  440.         (other-window 1)
  441.         (switch-to-buffer "*prolog*"))))
  442.  
  443. (defun kill-prolog-word (arg)
  444.   "Kill characters forward until encountering the end of a word.
  445. Treats underscore as a word if it appears as an argument.
  446. With argument, do this that many times."
  447.   (interactive "*p")
  448.   (kill-region (point) (progn (forward-prolog-word arg) (point))))
  449.  
  450. (defun backward-kill-prolog-word (arg)
  451.   "Kill characters backward until encountering the end of a word.
  452. With argument, do this that many times."
  453.   (interactive "*p")
  454.   (kill-prolog-word (- arg)))
  455.  
  456. (defun backward-term (arg)
  457.   (interactive "p")
  458.   (forward-term (- arg)))
  459.  
  460. (defun forward-term (arg)
  461.   (interactive "p")
  462.   (cond
  463.    ((zerop arg) t)
  464.    ((> arg 0)
  465.     (forward-sexp 1)
  466.     (if (= (following-char) ?\( )
  467.     (forward-sexp 1))
  468.     (forward-term (1- arg)))
  469.    (t
  470.     (forward-sexp -1)
  471.     (if (= (following-char) ?\( )
  472.     (forward-sexp -1))
  473.     (forward-term (1+ arg)))))
  474.  
  475. (defun forward-prolog-word (arg)
  476.   "Just like word forward, but it treats `_' like a word
  477. if it is used in the position that it is a anynomous
  478. variable"
  479.   (interactive "p")
  480.   (or arg (setq arg 1))
  481.   (cond
  482.    ((zerop arg) t)
  483.    ((> arg 0)
  484.     (if (looking-at "[(,]?\\s-*_\\s-*[),]")
  485.         (progn
  486.           (forward-char 1)
  487.           (re-search-forward "[),]")
  488.           (backward-char 1))
  489.       (forward-word 1))
  490.     (forward-prolog-word (1- arg)))
  491.    (t
  492.     (if (looking-at "_") (forward-char -1))
  493.     (if (looking-at "\\s-\\|$") (re-search-backward "\\S-"))
  494.     (cond
  495.      ((looking-at "[,)]")
  496.       (forward-char -1)
  497.       (if (looking-at "\\s-") (re-search-backward "\\S-"))
  498.       (if (not (looking-at "_"))
  499.           (progn
  500.             (forward-char 1)
  501.             (forward-word -1))))
  502.      ((looking-at "_") t)
  503.      (t (forward-word -1)))
  504.     (forward-prolog-word (1+ arg)))))
  505.  
  506. (defun backward-prolog-word (arg)
  507.   "Move backward until encountering the end of a word.
  508. With argument, do this that many times.
  509. In programs, it is faster to call forward-word with negative arg."
  510.   (interactive "p")
  511.   (forward-prolog-word (- arg)))
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.