Informative top-level prompt
Courtesy of Paul Foley: FWIW, I like to add
to my lisp.core, so I get a "USER> " prompt that changes as I change packages instead of the horrible default "* " prompt.
Correct package name for CMUCL 19a changes
To achieve the same effect in SBCL, use:
Using the prompt with ilispIf you want to use the prompt above in a ilisp buffer, add the following to you emacs startup-file (.emacs):
Turning off GC messages
... is as easy as setting ext:*gc-verbose* to NIL.
Behaviour of setq at top-level
Undoing a special declaration
If you find that you've accidentally created a special, you can undo it. CMUCL keeps this information in a database you can query/modify using ext:info.
* (setf x nil) Warning: Declaring X special. NIL ;; Uh oh * (ext:info :variable :kind 'x) :SPECIAL T ;; This changes X back to a lexical * (setf (ext:info :variable :kind 'x) :global) :GLOBAL
This works on SBCL too, using sb-ext:info
Using the MOP
The MOP in CMUCL is based on PCL and works pretty much like AMOP describes. There is however an oddity with it that has to do with ``wrapper'' classes, the details of which I (dan) unfortunately can't remember (so, somebody please edit this). Anyway, a reasonable fix is to work in a package that shadows a bunch of symbols from PCL instead of picking up the default versions in COMMON-LISP :
Running Lisp programs from the shell prompt
Note that this works on Linux systems only (tested on Slackware 7.0 by the original poster). Depends on having a kernel compiled with the binfmt_misc module enabled, and root access to setup binfmt_misc. Any user can run the scripts.
From: "Vladimir V. Zolotych" <firstname.lastname@example.org> Subject: Re: echo program Newsgroups: comp.lang.lisp Date: Wed, 28 Feb 2001 20:19:54 +0200 Organization: DCS-EuroCom ISP Here is the summary (Thanks to Paul Foley and Rudolf Schlatte) Using Slackware 7.0 The CL echo program (file ECHO.lisp) (loop for arg in *command-line-strings* as i upfrom 0 do (format t "~&arg[~D] = ~S" i arg)) (terpri) Shell script (file /usr/local/lib/batch) #!/bin/sh exec /usr/local/bin/lisp -batch -load $* Settings for binfmt_misc # cd /proc/sys/fs/binfmt_misc/ # echo ':CMUCL:M::FASL FILE::/usr/local/lib/batch:' >register Running ECHO.x86f $ echo.x86f 1 2 3 ; Loading #p"/home/vlz/.cmucl-init.lisp". ; Loading #p"/home/vlz/cmucl/echo/echo.x86f". arg = "/usr/local/bin/lisp" arg = "-batch" arg = "-load" arg = "./echo.x86f" arg = "1" arg = "2" arg = "3" $ -- Vladimir Zolotych email@example.com
(also see this page)
Note that it'd be even better to use
$* in the shell script to pass through all the
$* first concatenates all parameters, separating
them with space (the first character of
$IFS, in fact),
and after that, splits them again according to
My suggestion does NOT do this. This matters when some parameters
contain whitespace, such as
/some/program -name 'Hannah Schroeter'
Note that debian provides a wrapper ``cmucl-run'' with the cmucl package, which can be used with binfmt-support for binfmt_misc goodness.
CMUCL shell scripts
This is an alternative method to the linux-specific binfmt_misc method above, which should work on all Unix platforms. It consists of using a small trampoline program which invokes the CMUCL runtime with a rewritten argv. Your shell script looks something like
#!/usr/bin/cmucl-trampoline \ -quiet -batch -noinit !#
(format t "~&Hello, world!~%")
You need to download the cmucl-trampoline program, and your image must contain a reader macro which treats #!..!# as comments (there is example lisp in the code).
Another way relies on your shell automatically interpreting executable files not marked with #! itself:
":" ; exec lisp -load "$0" -eval '(quit)'or, to compile it first:
":" ; exec lisp -eval "(compile-file \"$0\")" -load `basename $0 .lisp`.x86f -eval '(quit)'
Here is what I (Erik Enge) use to write Lisp shellscripts:
#!/bin/sh # -*- mode: sh -*-
# $Id: runlisp,v 1.3 2003/04/22 02:33:53 erik Exp $ # $Source: /home/cvsd/repo/bin/runlisp,v $
# A handy script to run Lisp as shellscripts. In the top of your # file, put: # # #!/usr/bin/env runlisp # # and stick runlisp (this script) somewhere in your path. Then you # can have regular-looking shellscripts that are written in Lisp.
# If you have another Lisp implementation and know what arguments to # pass to it for this to work, feel free to add it and send me # (firstname.lastname@example.org) the patch.
if [ -f /usr/bin/sbcl ]; then /usr/bin/sbcl --noinform --disable-debugger --eval '(set-dispatch-macro-character #\# #\! (lambda (stream bang number) (declare (ignore bang number)) (read-line stream) t))' --load $1 --eval '(quit)' elif [ -f /usr/bin/lisp ]; then /usr/bin/lisp -quiet -batch -noinit -eval '(set-dispatch-macro-character #\# #\! (lambda (stream bang number) (declare (ignore bang number)) (read-line stream) t))' -load $1 -eval '(quit)' else echo "$0: could not find a Lisp I know how to call" fi
CLX over ssh-forwarded displays
The standard CLX function OPEN-DISPLAY doesn't correctly extract the display number from the DISPLAY environment variable. This is a problem you might run into when using CLX on an ssh-forwarded X11 session. Indeed, ssh typically sets $DISPLAY to remotehost:10, and forwards port 6010 on the remote host to port 6000 (or whatever port the local X11 server is running on) on the local host. CLX will unsuccessfully try to connect to remotehost:0.
The solution is to use the CMUCL-specific function EXT:OPEN-CLX-DISPLAY instead of XLIB:OPEN-DISPLAY. This function will parse the DISPLAY environment variable to extract the display and screen numbers.
Note that the version of CLX distributed with CMUCL includes a number of extensions to the original code. It is able to extract X11 authorization cookies from the file mentioned by the XAUTHORITY environment variable (defaulting to ~/.Xauthority), and it includes hooks into CMUCL's SERVE-EVENT facility.
NB: Many people seem to find that this does not work for them, as the question of how to use CLX locally without turning off access control is a frequent question on c.l.lisp and the CMUCL mailing list.
An example of CMUCL's SERVE-EVENT facility, that allows you to handle multiple concurrent network connections and file handles, without using multithreading. The program is a port forwarder, or redirector. It redirects TCP connections to another port on another machine. Get it from purl.org/net/emarsden/home/downloads/.
Adding commandline switches
Certain implementations such as CLISP have a -c commandline switch that allows you to invoke the file compiler from the shell. CMUCL's commandline switches are user-extensible, so you can emulate this behaviour with code such as the following, in your site-init.lisp or ~/.cmucl-init initialization files.
Now you can use the following to compile (and load) from the command line:
lisp -compile-and-load demo.lisp demo2.lisp
If errors are encountered during processing, CMUCL is aborted, with a return value of 1, otherwise it returns 0 (i.e. success). This can be combined with the -quiet flag (put it at the start of the commandline) if wanted.
An alternative to this form of interaction with the file compiler is to load the files and compile them from a stream, so you don't have any FASL files hanging around on disk (thus avoiding problems with binary compatibility between different CMUCL releases), yet still benefit from compiled performance. You can do this with code such as:
Adapted from article email@example.com posted to comp.lang.lisp by Pierre Mai, on 2001-11-30.
In CMUCL 18e and later, use fwrappers; the encapsulation mechanism described below is deprecated.
from the release notes for CMUCL 17f:
-- The encapsulation mechanism (similar to advise facilities) has been revamped to work on SETF function names as well as symbols. EXT:ENCAPSULATED-DEFINITION Returns whatever definition is stored for name, regardless of whether it is encapsulated. Unlike FDEFINITION, this does not strip off the encapsulation. This is SETF'able. EXT:ENCAPSULATE Replaces the definition of name with a function that binds name's arguments a variable named argument-list, binds name's definition to a variable named basic-definition, and EVAL's body in that context. Type is whatever you would like to associate with this encapsulation for identification in case you need multiple encapsuations of the same name. EXT:UNENCAPSULATE Removes name's most recent encapsulation of the specified type. EXT:ENCAPSULATED-P Returns t if name has an encapsulation of the given type, otherwise nil. EXT:*SETF-FDEFINITION-HOOK* A list of functions invoked by (SETF FDEFINITION) before storing the new value. Each hook function must take the function name and the new-value.
also see: section 3.10.1 of the CMUCL Users' Manual;
Command line editing and auto completion with CMUCL
For the rare cases when you don't use ILISP but invoke CMUCL directly from the command line:
- Get rlwrap and build it.
- Put something like
alias cmucl="rlwrap cmucl"into your
~/.inputrcfile (actually the file where
$INPUTRCpoints to). I added the line
TAB: completebecause rlwrap binds this key to
Note that recent readline versions include an example program rlfe that does almost the same thing as rlwrap. I think rlwrap is nicer, though. Update: I've slightly enhanced this hint (including a way to create better completions files) and put it here.
For those of you on Debian, cle that does pretty much the same thing (but no tab-completion) is packaged on testing.
Allegro-like REPL commands
To get top-level commands like
:load "foo.lisp" either use Paul Foley's version at http://users.actrix.co.nz/mycroft/toplevel/ or Peder O. Klingenberg's