Quintus Prolog Manual


(PREV) (NEXT)

d-2: The GNU Emacs Interface

d-2-1: Overview

This chapter presupposes some knowledge of the GNU Emacs editor. The next two sections summarize the features that have been added to GNU Emacs specifically to support Quintus Prolog. It should be noted that these features are not available with the standard GNU Emacs distribution. The Quintus Prolog distribution contains Emacs-Lisp code that constitutes the interface. Users are free to modify this interface in any way, provided they adhere to the copying policies of the Free Software Foundation. Read the file COPYING in the GNU Emacs distribution for further details.

To run Prolog under the Emacs interface, type a command such as

% prolog +



% prolog + command-line-arguments



at the operating system prompt. GNU Emacs processes command line arguments in two lots, described in two tables in the GNU Emacs Manual. Under the Quintus Prolog GNU Emacs interface, only switches from the first table can be used, and the most commonly used one is file-to-be-edited. (See {manual(g-3)} for full details of starting up Prolog.) Note however that the prolog buffer will not be displayed if the command-line-arguments includes files to be edited. In this case the last file specified on the command line is the one displayed. You can however switch to the prolog buffer by invoking the key binding to switch buffers (usually ^x b) and specifying the prolog buffer name "*prolog*".

Another way to start up the interface is from a QUI menu. See {manual(c-4-1)} for how to do this.

A third alternative is to start up Quintus Prolog from within GNU Emacs by typing 'Escape x run-prolog' (see {manual(d-1-1)} for a description of how to set the environment variable QUINTUS_PROLOG_PATH which should be set to the path name of a Prolog executable before you invoke this command. In addition you must specify the directories where the Emacs lisp files in the interface live and load them. Refer to the README file in the editor subdirectory of the Quintus distribution for details.) This should load in a specific set of '.el' or '.elc' files. These '.elc' files are part of the editor subdirectory of the Quintus distribution. ({manual(a-3)} explains the structure of the Quintus directory.)

With GNU Emacs, you can talk to Prolog very much as you would without the GNU Emacs interface. The only difference with GNU Emacs is that control characters issued to Prolog generally have their GNU Emacs meaning rather than any meaning they might have outside of GNU Emacs. The reason for this is that the Prolog window is still an edit buffer, and you are free to move up and down in it and modify its contents using the full range of editing commands. Thus ^d deletes a character, ^u may be used to specify an argument for the next command, and so on.

The general philosophy of the Prolog/GNU Emacs interface is that you should not be able to lose your Prolog prompt(by deleting a line, for example). For this reason, a few commands have been slightly modified. There are also a number of additional key bindings, which are described below.

GNU Emacs is a customizable editor. You can use a language called Emacs-Lisp to extend or alter the way it behaves, and in fact this is the way that the Prolog/GNU Emacs interface has been built. If you want to make your own extensions, you may need to know something about the way this interface works; notes to assist you are provided later in this chapter.

WARNING: The Prolog/GNU Emacs interface uses the control character '^]' for its communication. If this character has been made special by the UNIX command stty, the Prolog/GNU Emacs interface will not work. If there is a problem with the interface, you can use

stty all



to see all the special character settings and see if '^]' is shown.

d-2-2: Key Bindings

This section describes the key bindings associated with the Prolog/GNU Emacs interface. For a complete listing of all the key bindings applicable in a particular window, type 'Escape x describe-bindings' or '^h b'.

The following key bindings apply only in the Prolog window, not in the text window(s):

^c ^d
Sends an end-of-file to Prolog. This can be used to exit from a break level or to exit from Prolog altogether (see {manual(g-11-1)} for more information on break/0). Having exited from Prolog using this command, the only way of start up a new Prolog is by typing Escape x followed by "run-prolog".
^x ^z
Suspends Prolog and GNU Emacs.
^x ^e
Allows you to edit a query you previously typed to the Prolog prompt and resubmit it. Effectively, it grabs the last query and brings it down to the mini-buffer. There you can edit it if necessary, then move your cursor to the last line of the query and type Return. This places the query in the prolog window, where you can edit it further, if necessary, and type return to submit the query to Prolog. You can also grab queries other than the most recent one by specifying a prefix argument to this command (using Escape, or ^u): 2 to get the second last, 3 to get the third last, and so on. Another way to do this is to move the cursor back to the query you want to copy and type ^x ^e. This last alternative does not place the query in the mini-buffer but places it directly in the prolog window. In the cases where a query is placed in the mini-buffer, you can step up a list of previously executed queries by typing in 'Escape p' or down the list by typing in 'Escape n'. Since the mini-buffer is only one line, a multi-line query can be stepped around by using the conventional ^p, ^n key strokes. To obtain the set of bindings that are active within the mini-buffer when you execute the yank-query key sequence type in '^h b'. This method of stepping through a goal history is similar to GNU Emacs method of stepping through a command history.
^x ^y
Allows you to edit the most recent query matching a regular expression. You are first prompted for a regular expression; on entering a regular expression and hitting the Return key, the most recently submitted goal matching the regular expression is displayed in the mini-buffer. You can choose to submit this query to prolog (after editing it in the minibuffer, if necessary) or locate the next most recent goal matching the given regular expression.
^c ^c
Sends an interrupt to the Prolog process (exactly as if you were not running under GNU Emacs).

NOTE: to send a numeric argument to an GNU Emacs command, type Escape followed by the desired number (for example, Escape 1 or Escape 12); then type the command. ^u also works as an argument prefix, as in "standard" GNU Emacs.

The following key bindings apply in any window:

^x ^c
Causes an irreversible exit from GNU Emacs and Prolog. You will be prompted to make sure that (1) the Prolog and all other subprocesses should indeed be killed, and (2) any unsaved buffers should indeed be discarded.
^x ^z
Suspends (pauses) the GNU Emacs process and returns you to the operating system prompt. If a Prolog program is running, it will continue to run, but you will not see any output from it. You can get your GNU Emacs/Prolog session back by typing "fg" -- see the documentation for csh in the UNIX manual for further details. (This pause facility is only available if you are running csh; it does not work under sh.)
Escape .
Finds the source code for a particular procedure. If the cursor is positioned on or before the predicate name part of a goal, you can simply press the Return key to find the clauses for its procedure. Otherwise, in response to the prompt "name/arity = ", you should type the name of the predicate, optionally followed by a '/' and its arity. The file containing the procedure for the specified predicate is then visited, and the cursor is positioned at the beginning of the procedure. There are some layout conventions which must be followed for this facility to work: see {manual(d-2-4)}. The facility is also available via the '.' debugger option (see {manual(e)}). In QUI, find-definition must be invoked within the GNU Emacs process, not the QUI main window.
Escape ,
This command can only be used after 'Escape .'. It successively locates other procedure definition(s) for a predicate. 'Escape ,' will search other files for additional clauses for a multifile predicate, will search for a predicate of the same name and arity in a different module, or will search for predicates with the same name and different arities (in the case where the arity was not specified).
Escape x prolog-mode
Changes the current buffer to Prolog mode. See {manual(d-2-3)}.
Escape x library
Prompts for a file and locates it in the Quintus Prolog Library directories.

The following key bindings apply in any edit window except the Prolog window:

Escape k
(for "kompile") is used to load procedures from the edit buffer. You are then prompted to choose one of three options; you can compile
  1. the procedure in which the cursor is currently positioned (see {manual(d-2-4)}, for restrictions on program layout necessary for this to work);
  2. the region between the cursor and the mark; or
  3. the whole buffer.
Escape i
(for interpret) is synonymous for Escape k; and is there for backward compatibility.

d-2-3: Prolog Mode

Prolog mode applies automatically whenever you are editing a file which ends with the characters '.pl'. This mode is useful when you are editing Prolog source code. In Prolog mode:

d-2-4: Prolog Source Code Layout Restrictions

There are some restrictions on program layout which are necessary for 'Escape k p' (compiling a procedure), 'Escape .' (find-definition) and for indentation in prolog mode to work properly. In order for these commands to function correctly, you must:

  1. Group Prolog clauses of the same name and arity together. That is, do not intersperse clauses of one procedure with clauses of another. Normally breaching this restriction will cause a style warning (see {manual(b-2-5)}).
  2. Start the heads of all Prolog clauses at the beginning of the line; indent any additional lines for those clauses. Within prolog mode the TAB and the Linefeed can be used for indenting the current line as prolog code.
  3. If a comment continues onto another line, indent the continuation line(s).
  4. Do not write clause definitions that use operators in the heads of the clauses. For example, if you want to define clauses for '+'/2, then write the head of the clause in the form "+(A, B)" and not "A + B".

d-2-5: Rebinding Keys in Your Initialization File

You can customize GNU Emacs by defining key bindings and/or Emacs-Lisp functions in a special GNU Emacs initialization file called .emacs which must be kept in your home (login) directory.

When GNU Emacs is started, it loads your GNU Emacs initialization file, if you have one, before loading the Emacs-Lisp files defining the editor interface. This means that any key bindings which you make in this file may be overridden by the editor interface package. However, you can tailor the interface, if you wish, by defining one or both of the following "hook functions":

prolog-startup-hook
If a function by this name is defined, it will be called after all the initializations done on invoking Prolog through the editor interface are completed, and before the screen is displayed.
prolog-mode-hook
If a function by this name is defined, it will be called every time Prolog mode is entered. Prolog mode is entered every time you edit a file with a '.pl' extension, and can also be entered by using the command 'Escape x prolog-mode'.

For example, if you don't like incremental search, and you prefer to use Escape e for moving to the end of a sentence, rather than for enlarging the current window, then you should add the following function definition to your initialization file:

(defun

     prolog-startup-hook ()

        (global-set-key  "\C-s" 'search-forward)

        (global-set-key  "\C-r" 'search-reverse)

        (global-set-key  "\ee"  'forward-sentence)

        (global-set-key  "\e\e"

                         'enlarge-window))



Note that the command strings could be written as : "\C-s" (Backslash C-s) for example. This version of prolog-startup-hook also binds the useful "enlarge-window" command, which is normally on Escape e in this interface, to Escape Escape.

If you wish to change key bindings in Prolog mode, you should use local-set-key rather than global-set-key, because the effect of Prolog mode is local to a particular window. For example, if you don't like the way Linefeed works in Prolog mode, you can define

(defun

     prolog-mode-hook ()

        (local-set-key  "\C-j" 'newline-and-indent))



This restores the default binding of Linefeed.

d-2-6: Programming the Prolog/GNU Emacs Interface

This section describes how the user can program the Quintus Prolog/GNU Emacs interface. In order to make effective use of the interface, the user must be very familiar with GNU Emacs's extension language, Emacs-Lisp. Quintus does not provide support for users' Emacs-Lisp code.

Before deciding to use Emacs-Lisp code in your applications, you should be aware of two potential problems. First, Quintus does not support the GNU Emacs editor interface and as such reserves the right to change the editor environment at any time. This could render your non-Prolog code inoperative or irrelevant. Second, the Quintus Prolog Runtime Generator (RG) product, which is used by some customers who want to distribute a number of copies of Prolog application software inexpensively, does not currently support the GNU Emacs environment. Thus it will not run your Emacs-Lisp code.

With these cautions in mind, if you decide to use Emacs-Lisp code in your applications, these notes should have all of the information that you need to proceed. If your application is very complex, you may also find that you need to understand in some detail how the GNU Emacs interface is built. Quintus supplies with the distribution the Emacs-Lisp source code for the interface. You are free to go ahead and change any part of the interface to suit your needs but please be careful to follow the guidelines set by the Free Software Foundation as to how this should be done. These guidelines may be found in any standard distribution of the GNU Emacs editor. You will find the files help.el, commands.el, and qprocess.el especially useful, although depending upon what you are trying to do you may need information from any of the Emacs-Lisp source files.

d-2-6-1: Submitting Prolog Queries from GNU Emacs

GNU Emacs talks to Prolog by writing a Emacs-Lisp string in the form of a Prolog query (of any kind), terminated by a full-stop and prefixed by a special character code, to Prolog's standard input stream. When Prolog detects one of these prefixed queries in its term input stream, it executes the query as if it had been typed by the user at the top level. The query prefix character is ASCII 29.

As an example, define the function

(defun to-prolog ()

    (process-send-string "prolog"

              "\035nl,write(hello),nl.\n")

)



 

Upon invoking this function from GNU Emacs, the results of the query are displayed in the Prolog execution buffer. Notice that the Prolog process is called "prolog", the query prefix character (ASCII 29) is denoted in a Emacs-Lisp string by the octal escape sequence '\035', and the full-stop at the end of the query must be a period followed by a newline character (denoted in a Emacs-Lisp string by the escape sequence '\n').

To make things simpler, Quintus defines a Emacs-Lisp function called "send-prolog" which, given a query string as its one argument, sends that query to the Prolog process, prefixed by the query prefix character and followed by a full-stop. So the above function can be more clearly written as

        (defun to-prolog ()

            (send-prolog "nl,write(hello),nl")

        )



WARNING: GNU Emacs should only send a prefixed query to Prolog when Prolog is waiting for the user to type a term at the terminal. Note that this occurs not only when the user explicitly calls read/[1,2] but also when Prolog is at the top-level prompt.

d-2-6-2: Invoking Emacs-Lisp Functions from Prolog

Prolog talks to GNU Emacs by writing a sequence of one or more Emacs-Lisp function calls (including the parentheses) to the standard output stream, where this sequence is delimited by two special character codes. When GNU Emacs detects one of these delimited "packets" (as they are referred to in the Emacs-Lisp code) being written, it executes the function calls that occur between the delimiters. The packet start character is ASCII 30 and the packet end character is ASCII 29.

As an example, define and call the predicate

to_emacs :-

        put(30),

        write('(message "hello") (sit-for 50)'),

        put(29).



WARNING: Attempting to debug or interrupt (with ^c ^c) this predicate, thus submitting only a partial packet to GNU Emacs, will cause subsequent output to be considered as a continuation of the current packet and disaster will ensue. If such a situation occurs, try typing the command

        put(29).



 

to terminate the packet. You may want to consider using a critical region to prevent this problem -- see the library package critical.pl.

You will notice that after the message ("hello") is printed out in the message buffer (also called the minibuffer in GNU Emacs literature) and the "sit-for" period expires, it then disappears. This is a side-effect of the design of the GNU Emacs interface. Any Emacs-Lisp function which is called by Prolog should display messages using the function

        (&qp-message message-string)



where message-string must be a single string (this is unlike "message" which can take multiple strings; use the Emacs-Lisp function "concat" to make a single string out of multiple strings). This string will be displayed in the message buffer after GNU Emacs has processed the current "packet" from Prolog. Therefore, if you redefine the predicate as

        to_emacs :-

                put(30),

                write('(&qp-message "hello")'),

                put(29).



 

and reinvoke it, you will find that the message remains in the message buffer.

e: The Debugger


Copyright (C) 1997 AI International Ltd
contact: product support sales information