This is Info file jade.info, produced by Makeinfo-1.55 from the input file jade.texi. START-INFO-DIR-ENTRY * Jade: (jade). An editor for X11 and AmigaDOS END-INFO-DIR-ENTRY This is Edition 1.3, last updated 7 October 1994, of `The Jade Manual', for Jade, Version 3.2. Jade is a text editor for X11 (on Unix) and the Amiga. Copyright 1993, 1994 John Harper. Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. File: jade.info, Node: Process Objects, Next: Asynchronous Processes, Up: Processes Process Objects --------------- A "process object" is a type of Lisp object used to provide a link between a `physical' process running in the operating system and Jade's Lisp system. Each process object consists of a number of components (references to other Lisp objects); these components are used when the object is used to run a subprocess. Process objects which aren't currently being used to run a subprocess store the exit value of the last subprocess which was run on that object. - Function: processp OBJECT This function returns `t' when its argument is a process object. The programmer-accessible components of a process object are, "Output stream" A normal Lisp output stream (*note Output Streams::.), all data which the subprocess outputs to its `stdout' channel is copied to this output stream. *Note Process I/O::. "State change function" A Lisp function, called each time the state of the subprocess being run on the object changes. *Note Process States::. "Program name" The name of the program (a string) to execute when the subprocess is created. "Program arguments" A list of strings defining the arguments which the program executed is given. "Directory" When a subprocess is started its current working directory is set to the directory named by this component of its process object. "Connection type" Asynchronous subprocesses (*note Asynchronous Processes::.) use this component to decide how to connect to the I/O channels of the subprocess. Current options include pseudo-terminals and pipes. - Function: make-process &optional OUTPUT-STREAM STATE-FUNCTION DIRECTORY PROGRAM ARGS This functions creates and returns a new process object. *No subprocess will be started.* The optional arguments are used to define the values of the components of the new process object, any undefined components will be set to default or null values. For each component of a process object two functions exist; one to read the component's value in a specific process object, the other to set the component's value. - Function: process-prog PROCESS Returns the value of the program name component of the process object PROCESS. - Function: set-process-prog PROCESS PROG-NAME Sets the value of the program name component of the process object PROCESS to the string PROG-NAME, then returns PROG-NAME. - Function: process-args PROCESS Returns the value of the program arguments component of the process object PROCESS. - Function: set-process-args PROCESS ARG-LIST Sets the value of the program arguments component of the process object PROCESS to the list ARG-LIST, then returns ARG-LIST. - Function: process-dir PROCESS Returns the value of the directory component of the process object PROCESS. - Function: set-process-directory PROCESS DIRECTORY Sets the value of the directory component of the process object PROCESS to the string DIRECTORY, then returns DIRECTORY. File: jade.info, Node: Asynchronous Processes, Next: Synchronous Processes, Prev: Process Objects, Up: Processes Asynchronous Processes ---------------------- An "asynchronous process" is one that runs in parallel with the editor, basically this means that once the subprocess has been started (by the `start-process' function) Jade will carry on as normal. The event loop checks for output from asynchronous processes, any found is copied to the process' output stream, and calls the the process' state change function when necessary (*note Process States::.). When using asynchronous processes you have a choice as to the Unix mechanism used to connect the `stdin', `stdout' and `stderr' streams of the subprocess to Jade's process (note that whatever the choice `stdout' and `stderr' always go to the same place). The two options currently available are pipes or pseudo-terminals; in general pseudo-terminals should only be used to provide a direct interface between the user and a process (i.e. the `*shell*' buffer) since they allow job control to work properly. At other times pipes will be more efficient and are used by default. - Function: start-process &optional PROCESS-OBJECT PROGRAM &rest ARGS This function starts an asynchronous subprocess running on the process object PROCESS-OBJECT. If PROCESS-OBJECT is undefined a new process object is created (by calling the function `make-process' with all arguments undefined). The function always returns the process object which the subprocess has been started on. If for some reason the subprocess can't be created an error of type `process-error' is signalled. The optional argument PROGRAM is a string defining the name of the program to execute, it will be searched for in all the directories in the `PATH' environment variable. The ARGS are strings to pass to the subprocess as its arguments. When defined, the optional arguments overrule the values of the related components of the process object. The following example runs the `ls' program asynchronously, its output is inserted into the current buffer. (let ((process (make-process (current-buffer)))) (start-process process "ls" "-s")) Note that when Jade terminates it kills all of its asynchronous subprocesses which are still running without warning. - Function: process-connection-type PROCESS Returns the value of the connection type component of the process object PROCESS. See the documentation of the `set-process-connection-type' function for the values this may take. - Function: set-process-connection-type PROCESS SYMBOL Sets the value of the connection type component of the process object PROCESS to SYMBOL, then returns SYMBOL. SYMBOL should be one of the following symbols, `pty' Use pseudo-terminals to connect to subprocesses running asynchronously on this process object. `pipe' Use standard Unix pipes to connect, this is the default value of this component. File: jade.info, Node: Synchronous Processes, Next: Process I/O, Prev: Asynchronous Processes, Up: Processes Synchronous Processes --------------------- When a "synchronous process" is started Jade waits for it to terminated before continuing; they are usually used when a Lisp program must invoke an external program as part of its function, i.e. the auto-compression feature runs the compression program `gzip' synchronously when it needs to compress a buffer. Unlike asynchronous processes their is no choice between pipes and pseudo-terminals for connecting to a subprocess. Instead, it is possible to link the `stdin' channel of a synchronous process to a named file. - Function: run-process &optional PROCESS-OBJECT INPUT-FILE-NAME PROGRAM &rest ARGS This function starts a process running on the process object PROCESS-OBJECT. If PROCESS-OBJECT is undefined a new process object is created by calling the `make-process' function. If defined, the string INPUT-FILE-NAME names the file to connect to the standard input of the subprocess, otherwise the subprocess' input comes from the null device (`/dev/null'). The optional arguments PROGRAM and ARGS define the name of the program to invoke and any arguments to pass to it. The program will be searched for in all directories listed in the `PATH' environment variable. If any of the optional parameters are unspecified they should have been set in the PROCESS-OBJECT prior to calling this function. After successfully creating the new subprocess, this function simply copies any output from the process to the output stream defined by the output stream component of the process object. When the subprocess exits its exit-value is returned (an integer). Note that the exit-value is the value returned by the `process-exit-value' function, see *Note Process Information::. If, for some reason, the new subprocess can't be created an error of type `process-error' is signalled. The following function definition is taken from the `gzip.jl' file, it shows how the `run-process' function can be used to uncompress a file into a buffer. ;; Uncompress FILE-NAME into the current buffer (defun gzip-uncompress (file-name) (let ((proc (make-process (current-buffer)))) (message (concat "Uncompressing `" file-name "'") t) ;; gunzip can do .Z files as well (unless (zerop (run-process proc nil "gunzip" "-c" file-name)) (signal 'file-error (list "Can't gunzip file" file-name))))) File: jade.info, Node: Process I/O, Next: Process States, Prev: Synchronous Processes, Up: Processes Process I/O ----------- It is only possible for lisp programs to explicitly send input data to *asynchronous* processes (by the time it's possible to call a function to send data to a synchronous process, the process will already have terminated!). Simply use the process object which an asynchronous process is running on as a normal Lisp input stream, any strings or characters written to the stream will immediately be copied to the `stdin' channel of the subprocess. With synchronous processes, the only control over input data possible is by giving the `run-process' function the name of a file containing the subprocess' input data. Output data from subprocesses is handled the same way by both asynchronous and synchronous processes: it is simply copied to the stream defined by the output stream component of the subprocess' process object. - Function: process-output-stream PROCESS Returns the value of the output stream component of the process object PROCESS. - Function: set-process-output-stream PROCESS STREAM Sets the value of the output stream component of the process object PROCESS to the stream STREAM, then returns STREAM. *Note Streams::. File: jade.info, Node: Process States, Next: Signalling Processes, Prev: Process I/O, Up: Processes Process States -------------- Each process object has a "state" associated with it; this depends on the status of the subprocess currently running on the process object (or not as the case may be). The possible states are, "running" This state means that the subprocess using this process object is currently running, i.e. it hasn't been stopped. "stopped" Means that the subprocess has been temporarily suspended from running. "unused" This means that the process object is free to have a new subprocess created on it. Predicates exist which test whether a given process object is in one of these states. - Function: process-running-p PROCESS-OBJECT Returns `t' when PROCESS-OBJECT is in the running state. - Function: process-stopped-p PROCESS-OBJECT Returns `t' when PROCESS-OBJECT is in the stopped state. - Function: process-in-use-p PROCESS-OBJECT Returns `t' when PROCESS-OBJECT is *not* in the unused state. The following two functions are used to stop and then subsequently continue a process running. - Function: stop-process PROCESS-OBJECT &optional WHOLE-GROUP This function suspends execution of the subprocess running on the process object PROCESS-OBJECT. If WHOLE-GROUP is non-`nil' all subprocesses in the process group of PROCESS-OBJECT are stopped. - Function: continue-process PROCESS-OBJECT &optional WHOLE-GROUP Use this function to continue a subprocess executing after it has been stopped (by the `stop-process' function). If WHOLE-GROUP is non-`nil' all subprocesses in the process group of PROCESS-OBJECT are continued. The state change function component of a process object defines a function which will be called each time the state of the process object changes. If your program needs to be informed when an asynchronous process terminates this function is the way to do it. - Function: process-function PROCESS Returns the value of the state change function component of the process object PROCESS. - Function: set-process-function PROCESS FUNCTION Sets the value of the state change function component of the process object PROCESS to the function FUNCTION, then returns FUNCTION. File: jade.info, Node: Signalling Processes, Next: Process Information, Prev: Process States, Up: Processes Signalling Processes -------------------- - Function: signal-process PROCESS-OBJECT SIGNAL-NUMBER &optional WHOLE-GROUP If the process object PROCESS-OBJECT is being used to run an asynchronous subprocess send the signal numbered SIGNAL-NUMBER to it. When the optional argument WHOLE-GROUP is non-`nil' the signal is also sent to all processes in the process group of the subprocess. The following functions use the `signal-process' function to send some common signals to processes. - Function: interrupt-process PROCESS-OBJECT &optional WHOLE-GROUP Sends the `SIGINT' signal to PROCESS-OBJECT. (interrupt-process PROCESS-OBJECT WHOLE-GROUP) == (signal-process PROCESS-OBJECT `SIGINT' WHOLE-GROUP) - Function: kill-process PROCESS-OBJECT &optional WHOLE-GROUP Sends the `SIGKILL' signal to the PROCESS-OBJECT. (kill-process PROCESS-OBJECT WHOLE-GROUP) == (signal-process PROCESS-OBJECT `SIGKILL' WHOLE-GROUP) Note that the functions `stop-process' and `continue-process' also send signals to the subprocess. File: jade.info, Node: Process Information, Next: Interactive Processes, Prev: Signalling Processes, Up: Processes Process Information ------------------- - Function: process-id PROCESS-OBJECT This function returns the operating-system identifier associated with the subprocess currently running on the process object PROCESS-OBJECT. - Function: process-exit-value PROCESS-OBJECT Returns the integer representing the return code of the last subprocess to be run on PROCESS-OBJECT. If no subprocess has been run on PROCESS-OBJECT, PROCESS-OBJECT is currently in the running state or the last subprocess exited abnormally (i.e. from a terminal signal) `nil' is returned. - Function: process-exit-status PROCESS-OBJECT This function returns the integer that was the exit status of the last subprocess which was run on the process object PROCESS-OBJECT. Note that the exit status is *not* the value given to the `exit' function in a C program, use the `process-exit-value' to access this value. If no process has been run on PROCESS-OBJECT, or the process is currently in the running state `nil' is returned. File: jade.info, Node: Interactive Processes, Prev: Process Information, Up: Processes Interactive Processes --------------------- The Shell mode is usually used to run a shell process in a buffer (with the `shell' command, *note Shell::.) but in actual fact it is capable of running (nearly) any type of interactive process. For example the gdb interface (*note Debugging Programs::.) uses the Shell mode to handle its user interaction. The following buffer-local variables control the Shell mode. - Variable: shell-program This variable defines the name of the program to execute. By default it is the user's shell. - Variable: shell-program-args A list of arguments which should be given to the process when it is started. - Variable: shell-prompt-regexp This regular expression must match the prompt that the process emits each time it waits for input. Its standard value of `^[^]#$%>)]*[]#$%>)] *' will need to be tailored to the program that you are executing. - Variable: shell-callback-function Every time the state of the subprocess changes (*note Process States::.) this function is called in the context of the process' buffer. - Variable: shell-output-stream All output from the subprocess is copied to this output stream. If it is `nil' all output goes to the end of the process' buffer. Note that this variable is only referenced when the process is started. To use the Shell mode to create an interface with a program simply use the following steps. 1. Select the buffer which you want to run the subprocess in. The value of the `buffer-file-name' attribute of the buffer defines the working directory of the subprocess. 2. Set the variables described above to suitable values. 3. Call the `shell-mode' function. 4. Reset the values of the `mode-name' and `major-mode' if necessary and install your own keymaps. Remember that commands essential to the Shell mode (and hence your program) are contained in the two keymaps `shell-keymap' and `shell-ctrl-c-keymap'. If you need to bind your own commands to either of these prefixes make copies of these keymaps (using the function `copy-sequence') and bind to the copies. For example the gdb interface installs its own key bindings from the `Ctrl-c' prefix by doing the following in its initialisation. (defvar gdb-ctrl-c-keymap (copy-sequence shell-ctrl-c-keymap)) (bind-keys gdb-ctrl-c-keymap ;; Gdb mode `Ctrl-c' prefix bindings follow ... - Function: shell-mode This function installs the Shell mode and starts a subprocess running in the current buffer. The variables `shell-program', `shell-program-args', `shell-prompt-regexp', `shell-callback-function' and `shell-output-stream' control the program executed and how it will execute. The process object created is stored in the buffer-local variable `shell-process'. - Variable: shell-process This buffer-local variable contains the process object which the Shell mode started running in this buffer. If it is `nil' no such process exists. - Variable: shell-keymap The root keymap of the Shell mode. - Variable: shell-ctrl-c-keymap The keymap containing the key bindings of the commands in Shell mode with a prefix of `Ctrl-c'. See the Lisp program `gdb.jl' for an example of how to use the Shell mode as the user interface with an external program. File: jade.info, Node: Miscellaneous Functions, Next: Debugging, Prev: Processes, Up: Programming Jade Miscellaneous Functions ======================= This section of the manual documents functions and features which don't comfortably fit elsewhere in this manual. * Menu: * System Information:: Getting details about the host * User Information:: The name of the user * Environment Variables:: Reading and writing the environment * System Time:: Getting the current time * Revision Information:: How to check Jade's revision numbers File: jade.info, Node: System Information, Next: User Information, Up: Miscellaneous Functions System Information ------------------ - Function: x11-p This function returns `t' when Jade is running on the X11 window system. - Function: unix-p This function returns `t' when Jade is running on a variant of the Unix operating system. - Function: amiga-p This function returns `t' when Jade is running on an Amiga. - Function: system-name This function returns a string naming the host that Jade is running on. When possible this will include the name of the domain as well. In the Amiga version of Jade the environment variable `HOSTNAME' is assumed to contain the host's name. File: jade.info, Node: User Information, Next: Environment Variables, Prev: System Information, Up: Miscellaneous Functions User Information ---------------- - Function: user-login-name This function returns a string containing the login name of the user. In the Amiga version this is taken from the environment variable `USERNAME'. (user-login-name) => "jsh" - Function: user-real-name This function returns a string containing the `real' name of the user; the format of the string will depend on the host system. In the Amiga version this is taken from the `REALNAME' environment variable. (user-real-name) => "John Harper" - Function: user-home-directory This function returns the name of the user's home directory terminated by a slash character (`/'). The first place this is looked for is in the `HOME' environment variable; if this variable doesn't exist we either use the `SYS:' logical device in AmigaDOS or consult the passwd file when in Unix. (user-home-directory) => "/home/jsh/" File: jade.info, Node: Environment Variables, Next: System Time, Prev: User Information, Up: Miscellaneous Functions Environment Variables --------------------- - Function: getenv VARIABLE-NAME This function returns the value (a string) of the environment variable called VARIABLE-NAME. If the specified variable doesn't exist `nil' is returned. (getenv "OSTYPE") => "Linux" - Function: setenv VARIABLE-NAME NEW-VALUE This function sets the value of the environment variable called VARIABLE-NAME to NEW-VALUE. NEW-VALUE can either be a string containing the new contents of the variable or `nil', in which case the environment variable is deleted. File: jade.info, Node: System Time, Next: Revision Information, Prev: Environment Variables, Up: Miscellaneous Functions System Time ----------- No matter what operating system Jade is running on it always an integer to store a time value. Generally this will be the number of seconds since some previous date. The only thing a Lisp program is allowed to assume about a time value is that as time passes the time value *increases*. This means that it's possible to compare two time values and know which is the newer. - Function: current-time Returns an integer denoting the current time. (current-time) => 780935736 - Function: current-time-string This function returns a string stating the current time and date in a fixed format. An example of the format is, Fri Sep 30 15:20:56 1994 Each field will always be in the same place, for example, Thu Sep 1 12:13:14 1994 (current-time-string) => "Fri Sep 30 15:20:56 1994" File: jade.info, Node: Revision Information, Prev: System Time, Up: Miscellaneous Functions Revision Information -------------------- - Function: major-version-number This function returns a number defining the major version of the editor. (major-version-number) => 3 - Function: minor-version-number Returns a number defining the minor version of the editor. (minor-version-number) => 2 File: jade.info, Node: Debugging, Next: Tips, Prev: Miscellaneous Functions, Up: Programming Jade Debugging ========= When you have written a Lisp program you will have to debug it (unless all your programs work first time?). There are two main classes of errors; syntax errors and semantic errors. Syntax errors occur when the text you've typed out to represent your program is not a valid representation of a Lisp object (since a program is simply an ordered set of Lisp objects). When you try to load your program the Lisp reader will find the syntax error and tell you about, unfortunately though it probably won't be able to tell you exactly where the error is. The most common source of syntax errors is too few or too many parentheses; the `Ctrl-Meta-f' and `Ctrl-Meta-b' commands can be used to show the structure of the program as the Lisp reader sees it. Semantic errors are what we normally call bugs -- errors in logic, the program is syntactically correct but doesn't do what you want it to. For these types of errors Jade provides a simple debugger which allows you to single step through the Lisp forms of your program as they are being evaluated. There are several ways to enter the Lisp debugger; functions can be marked so that they cause the debugger to be entered when they are called, breakpoints can be written in functions or it can be called explicitly with a form to step through. - Command: trace SYMBOL This command marks the symbol SYMBOL so that each time the function stored in the function cell of SYMBOL is called the debugger is entered immediately. When called interactively SYMBOL is prompted for. - Command: untrace SYMBOL The opposite of `trace' -- unmarks the symbol. - Function: break This function causes the debugger to be entered immediately. By putting the form `(break)' at suitable points in your program simple breakpoints can be created. - Command: step FORM This function invokes the debugger to step through the form FORM. When called interactively FORM is prompted for. Whenever the Lisp debugger is entered the form waiting to be evaluated is printed at the bottom of the buffer, at this point the special debugger commands available are, `Ctrl-c Ctrl-s' Step into the current form; this means that in a list form the debugger is used to evaluated each argument in turn. `Ctrl-c Ctrl-i' Ignore the current form; makes the current form immediately return `nil'. `Ctrl-c Ctrl-n' Continue evaluating forms normally until the next form at the current level is entered, then re-enter the debugger. `Ctrl-c Ctrl-r' Continue execution normally. Note that this command is the one to use when an error has been trapped. `Ctrl-c Ctrl-b' Print a backtrace of the current Lisp call stack, note that calls of primitive functions aren't currently recorded in this stack. `Ctrl-c Ctrl-x' Prompt for a Lisp form, evaluate it and return this value as the result of the current form. After the form has been evaluated (i.e. after you've typed one of the commands above) the value of the form is printed in the buffer, prefixed by the string `=> '. Note that it is also possible to make certain types of errors invoke the debugger immediately they are signalled, see *Note Errors::. File: jade.info, Node: Tips, Prev: Debugging, Up: Programming Jade This section of the manual gives advice about programming in Jade. Obviously there is no *need* to religiously follow every single one, but following these tips will make your programs easier to read and (hopefully) more efficient overall. For advice on getting the most out of the compiler, see *Note Compilation Tips::. * Menu: * Comment Styles:: Differrent types of comments * Program Layout:: How I lay out the programs I write * General Tips:: Do's and Don't's of Jade programming File: jade.info, Node: Comment Styles, Next: Program Layout, Up: Tips Comment Styles -------------- As already described, single-line comments in Lisp are introduced by a semi-colon (`;') character. By convention a different number of semi-colons is used to introduce different types of comments, A comment referring to the line of Lisp code that it occurs on, comments of this type are usually indented to the same depth, on the right of the Lisp code. When editing in Lisp mode the command `Meta-;' can be used to insert a comment of this type. For example, (defconst op-call 0x08) ;call (stk[n] stk[n-1] ... stk[0]) ; pops n values, replacing the ; function with the result. (defconst op-push 0x10) ;pushes constant # n Comments starting with two semi-colons are written on a line of their own and indented to the same depth as the next line of Lisp code. They describe the following lines of code. For example, ;; Be sure to remove any partially written dst-file. (let ((fname (concat file-name ?c))) (when (file-exists-p fname) (delete-file fname))) Comments of this type are also placed before a function definition to describe the function. This saves wasting memory with a documentation string in a module's internal functions. For example, ;; Compile a form which occurred at the `top-level' into a ;; byte code form. ;; defuns, defmacros, defvars, etc... are treated specially. ;; require forms are evaluated before being output uncompiled; ;; this is so any macros are brought in before they're used. (defun comp-compile-top-form (form) ... `;;;' This type of comment always starts in the first column of the line, they are used to make general comments about a program and don't refer to any function or piece of code in particular. For example, ;;; Notes: ;;; ;;; Instruction Encoding ;;; ==================== ;;; Instructions which get an argument (with opcodes of zero up to ... `;;;;' Each program should have a comment of this type as its first line, the body of the comment is the name of the file, two dashes and a brief description of what the program does. They always start in the first column. For example, ;;;; compiler.jl -- Simple compiler for Lisp files/forms If you adhere to these standards the indentation functions provide by the Lisp mode will indent your comments to the correct depth. File: jade.info, Node: Program Layout, Next: General Tips, Prev: Comment Styles, Up: Tips Program Layout -------------- The layout that I have used for all the Lisp programs included with Jade is as follows, obviously this isn't ideal but it seems ok. 1. The first line of the file is the header comment, including the name of the file and its general function. 2. Copyright banner. 3. Any `require' forms needed followed by a `provide' form for this module. The `require' forms should be before the `provide' in case the required modules aren't available. 4. Variable and constant definitions. As a variable is defined any initialisation it needs is done immediately afterwards. For example a keymap is defined with `defvar' then initialised with the `bind-keys' function. For example, (defvar debug-buffer (make-buffer "*debugger*") "Buffer to use for the Lisp debugger.") (set-buffer-special debug-buffer t) (add-buffer debug-buffer) (defvar debug-ctrl-c-keymap (make-keylist) "Keymap for debugger's ctrl-c prefix.") (bind-keys debug-ctrl-c-keymap "Ctrl-s" 'debug-step ... 5. Finally the functions which make up the program, it often improves readability if the entry points to the program are defined first. File: jade.info, Node: General Tips, Prev: Program Layout, Up: Tips General Tips ------------ The following are some general items of advice; you don't have to follow them but they are the result of experience! * Jade only has one name-space for all the symbols ever created, this could lead to naming clashes if care isn't taken. When you write a program all the symbols it creates should be prefixed by a name derived from the name of the program in some way. For example, in the program `isearch.jl' all functions and variable names are prefixed by the string `isearch-', giving `isearch-cancel' and so on. Note that the prefix doesn't have to be the exact name of the file, the program `buffer-menu.jl' uses the prefix `bm-'. The entry points to a module (i.e. the names of the commands it provides) should *not* have a prefix, simply give them a descriptive name (but try not to make it too long!). Don't bother giving local variables these prefixes unless they are used by several functions in the program. * Use the `recursive-edit' function as little as possible; it can be *very* confusing for the user! When at all possible use keymaps to create user interfaces. * Use the Lisp mode to indent your programs; not only does it save a lot of time it also makes it easier for other people to read them. * Errors should always be reported by either `error' or `signal', don't just print a message or call `beep'. * Don't redefine existing functions unless absolutely possible: try to use hooks. If there is no hook where you want one, mail me about it and I may put one in the next release. * Don't compile your program until you're sure it works! The debugger only works properly with uncompiled code. * Use constants sparingly: personally, I only use them where the constants are numeric. * Remember to define macros before they are used, otherwise they won't be compiled inline. The same can happen if you don't `require' a file that a macro is defined in before using the macro definition. * As I said in the compilation tips (*note Compilation Tips::.), try to use iteration instead of recursion. Also the `memq' and `assq' types of functions can be used to search some types of list structures very quickly. * When writing modes don't bind any unmodified keys to the prefix `Ctrl-c', these are reserved for customisation by users. File: jade.info, Node: Reporting Bugs, Next: Function Index, Prev: Programming Jade, Up: Top Reporting Bugs ************** If you think you've found a bug in Jade I want to know about it, there is a list of problems that I am aware of in the `src/BUGS' file, if yours appears in there tell me anyway to make me fix it. When submitting bug reports I need to know as much as possible, both about the problem and the circumstances in which it occurs. In general, send me as much information as possible, even if you think it's probably irrelevant. If you can, contact me via email, my address is `jsh@ukc.ac.uk'. If you don't get a reply within about a week it's probably a university vacation -- this means that I won't get your message for a while; if it's important try my postal address, this is, John Harper 91 Springdale Road Broadstone Dorset BH18 9BW England As well as bugs I'm interested in any comments you have about the editor, even if you just tell me you hate it (as long as you say *why* you hate it!).