Courtesy of Paul Foley: FWIW, I like to add (in-package "COMMON-LISP") (defvar *last-package* nil) (defvar *cached-prompt*) (defun tpl-prompt () (unless (eq *last-package* *package*) (setf *cached-prompt* (concatenate 'string (or (first (package-nicknames *package*)) (package-name *package*)) "> ")) (setf *last-package* *package*)) *cached-prompt*) (setf *prompt* #'tpl-prompt) to my lisp.core, so I get a "USER> " prompt that changes as I change packages instead of the horrible default "* " prompt.
(in-package "LISP")
(defvar *last-package* nil) (defvar *cached-prompt* nil) (defun package-prompt (stream) (unless (eq *last-package* *package*) (setf *cached-prompt* (concatenate 'string (or (first (package-nicknames *package*)) (package-name *package*)) "> ")) (setf *last-package* *package*)) (terpri) (princ *cached-prompt* stream)) (setf sb-int:*repl-prompt-fun* #'package-prompt)
(add-hook 'cmulisp-hook (lambda () (setq comint-prompt-regexp "^\\([0-9]+\\]+\\|\\*\\|[-a-zA-Z0-9]*\\[[0-9]+\\]:\\|[-A-Z0-9]*>\\) ") ))
(setq foo "bar")
(describe 'ext:*top-level-auto-declare*)
* (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
(defpackage "MY-PACKAGE" (:shadowing-import-from PCL FIND-CLASS CLASS-NAME BUILT-IN-CLASS CLASS-OF) ... )
From: "Vladimir V. Zolotych" 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[0] = "/usr/local/bin/lisp" arg[1] = "-batch" arg[2] = "-load" arg[3] = "./echo.x86f" arg[4] = "1" arg[5] = "2" arg[6] = "3" $ -- Vladimir Zolotych gsmith@eurocom.od.ua
${1+"$@"}
$*
$* first concatenates all parameters, separating them with space (the first character of $IFS, in fact), and after that, splits them again according to $IFS. My suggestion does NOT do this. This matters when some parameters contain whitespace, such as /some/program -name 'Hannah Schroeter' -- Hannah Schr?ter hannah@schlund.de, 22 May 2001
$IFS
/some/program -name 'Hannah Schroeter'
hannah@schlund.de
#!/usr/bin/cmucl-trampoline \ -quiet -batch -noinit !# (format t "~&Hello, world!~%")
":" ; exec lisp -load "$0" -eval '(quit)'
":" ; exec lisp -eval "(compile-file \"$0\")" -load `basename $0 .lisp`.x86f -eval '(quit)'
#!/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 # (erik@nittin.net) 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
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.
(macrolet ((with-batch-processing (&body body) `(handler-case (prog1 t ,@body) (serious-condition (condition) (format *error-output* "Error in batch processing:~%~A~%" condition) (finish-output *error-output*) (throw 'lisp::%end-of-the-world 1)) (:no-error (value) (declare (ignore value)) (throw 'lisp::%end-of-the-world 0))))) (ext:defswitch "compile" #'(lambda (switch) (with-batch-processing (mapc #'compile-file (ext:cmd-switch-words switch))))) (ext:defswitch "compile-and-load" #'(lambda (switch) (with-batch-processing (mapc #'(lambda (file) (compile-file file :load t)) (ext:cmd-switch-words switch))))) ) ; macrolet
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:
(defun process-switch-demon (switch) (let ((files (copy-list (ext:cmd-switch-words switch)))) (push #'(lambda () (dolist (file files) (format *terminal-io* "~&;;; Processing compiled code from ~A.~%" file) (with-open-file (s file) (ext:compile-from-stream s)))) *run-actions*))) (ext:defswitch "process" #'process-switch-demon)
Adapted from article 87g06vubxi.fsf@orion.bln.pmsf.de posted to comp.lang.lisp by Pierre Mai, on 2001-11-30.
-- 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; (describe 'ext:encapsulate)
(describe 'ext:encapsulate)
alias cmucl="rlwrap cmucl"
~/.bashrc
~/.profile
~/.cmucl_completions
~/.inputrc
$INPUTRC
TAB: complete
menu-complete
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.
:load "foo.lisp"