So, now I'm following along with the first practical from "Practical Common
Lisp". It all works great AND I'm understanding what I'm doing!
However, as I'm building up the functionality interactively via REPL, how
the heck do I save what I've accumulated in REPL to a .lisp file for later
use/modification?
I ended up saving the REPL buffer, but then I have to edit out the prompts,
commands and output to get a clean .lisp file. There must be an *easier*
way to do this.
Yes, I know, if I'm patient and retype stuff long enough I'll stumble
across this knowledge. Someone please help me with a shortcut <G>
> OK, so I get lispbox installed with clisp 2.37 ... it's all good
>
> So, now I'm following along with the first practical from "Practical Common
> Lisp". It all works great AND I'm understanding what I'm doing!
>
> However, as I'm building up the functionality interactively via REPL, how
> the heck do I save what I've accumulated in REPL to a .lisp file for later
> use/modification?
Short version, you don't; you write your actual code in other files.
For a longer version, see Chapter 2 of PCL, starting from the header
"Saving Your Work".
-Peter
--
Peter Seibel * pe...@gigamonkeys.com
Gigamonkeys Consulting * http://www.gigamonkeys.com/
Practical Common Lisp * http://www.gigamonkeys.com/book/
http://common-lisp.net/movies/slime.mov
It covers the basics of SLIME very well and is a great example of
excellent REPL usage.
> BobF <rNfOrS...@charter.net> writes:
>
>> OK, so I get lispbox installed with clisp 2.37 ... it's all good
>>
>> So, now I'm following along with the first practical from "Practical Common
>> Lisp". It all works great AND I'm understanding what I'm doing!
>>
>> However, as I'm building up the functionality interactively via REPL, how
>> the heck do I save what I've accumulated in REPL to a .lisp file for later
>> use/modification?
>
> Short version, you don't; you write your actual code in other files.
> For a longer version, see Chapter 2 of PCL, starting from the header
> "Saving Your Work".
>
> -Peter
I guess that explains why Chapter 2-Saving Your Work says "retype". This
seems terribly inefficient to me. There must be a way to at least list a
from in REPL so it can be copied pasted into a source file. Oh well ...
If you are using SLIME, you are already working in an Emacs
buffer. No need to `retype' anything then. Just move back
through your buffer's scrollback history and copy/paste :)
- Giorgos
Second thing, you can compile individual methods in your source file by
putting the point somewhere in the method ant typing ctrl-C twice.
Thanks. I finally figured that one out.
Thanks for the tip.
I appreciate the help guys.
(selectively-snipped-or-not-p)
> > Short version, you don't; you write your actual code in other files.
> > For a longer version, see Chapter 2 of PCL, starting from the header
> > "Saving Your Work".
> >
> > -Peter
>
> I guess that explains why Chapter 2-Saving Your Work says "retype". This
> seems terribly inefficient to me. There must be a way to at least list a
> from in REPL so it can be copied pasted into a source file. Oh well ...
Or activate te the type-out-buffer in your .emacs.el like:
then editing it toshape, saving is hardly a burden.
like:
;; enhanced SLIME-settings
;(slime-setup :autodoc t)
;(add-hook 'slime-connected-hook 'slime-ensure-typeout-frame)
;(global-set-key "\C-cs" 'slime-selector)
Cor
--
I do not use Windows (tm) therefore I do not fear mail from strangers
If everything else failed to satisfy you, try reading The Frign' Manual
(defvar My-Computer '((OS . "GNU/Emacs") (IPL . "GNU/Linux")))
http://www.clsnet.nl
Once your comfortable with the basics, you can open a file under
emacs, set it to slime-mode with M-x slime-mode (this can be automated
based on file extensions and the use of the auto-model-alist
variable). Now, after you define a function, you can send it to the
repl in various ways. Often, you will split the screen in two with the
file in one window and the repl in the other. Then you can use the
repl to experiment and evaluate simple things - then write the
function in the file window, send it to the repl for evaluation and
move to the next bit etc.
Tim
--
tcross (at) rapttech dot com dot au
Thanks, Tim. I'm using the split window approach. I'm just looking for a
quick & easy way to move code back and forth between windows. Cut/Paste
has me moving along for now.
> O
> Some entity AKA BobF <rNfOrS...@charter.net>
> wrote this mindboggling stuff:
>
> (selectively-snipped-or-not-p)
>
>>> Short version, you don't; you write your actual code in other files.
>>> For a longer version, see Chapter 2 of PCL, starting from the header
>>> "Saving Your Work".
>>>
>>> -Peter
>>
>> I guess that explains why Chapter 2-Saving Your Work says "retype". This
>> seems terribly inefficient to me. There must be a way to at least list a
>> from in REPL so it can be copied pasted into a source file. Oh well ...
>
> Or activate te the type-out-buffer in your .emacs.el like:
> then editing it toshape, saving is hardly a burden.
>
> like:
> ;; enhanced SLIME-settings
> ;(slime-setup :autodoc t)
> ;(add-hook 'slime-connected-hook 'slime-ensure-typeout-frame)
> ;(global-set-key "\C-cs" 'slime-selector)
>
> Cor
Thanks for the tip. I'll get to the cryptic stuff in a few years or so <g>
> OK, so I get lispbox installed with clisp 2.37 ... it's all good
>
> So, now I'm following along with the first practical from "Practical Common
> Lisp". It all works great AND I'm understanding what I'm doing!
>
> However, as I'm building up the functionality interactively via REPL, how
> the heck do I save what I've accumulated in REPL to a .lisp file for later
> use/modification?
>
> I ended up saving the REPL buffer, but then I have to edit out the prompts,
> commands and output to get a clean .lisp file. There must be an *easier*
> way to do this.
You could prepare an image-based-common-lisp image with the following
command and two files.
% ibcl
i i i i i i i ooooo o ooooooo ooooo ooooo
I I I I I I I 8 8 8 8 8 o 8 8
I \ `+' / I 8 8 8 8 8 8
\ `-+-' / 8 8 8 ooooo 8oooo
`-__|__-' 8 8 8 8 8
| 8 o 8 8 o 8 8
------+------ ooooo 8oooooo ooo8ooo ooooo 8
Copyright (c) Bruno Haible, Michael Stoll 1992, 1993
Copyright (c) Bruno Haible, Marcus Daniels 1994-1997
Copyright (c) Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998
Copyright (c) Bruno Haible, Sam Steingold 1999-2000
Copyright (c) Sam Steingold, Bruno Haible 2001-2006
[1]> *package*
#<PACKAGE IMAGE-BASED-COMMON-LISP-USER>
[2]> (defun fact (x) (if (< 1 x) 1 (* x (fact (1- x)))))
FACT
[3]> (fact 3)
1
[4]> (get-source 'function 'fact)
(DEFUN FACT (X) (IF (< 1 X) 1 (* X (FACT (1- X))))) ;
T
[5]> (ed 'fact)
Waiting for Emacs...
(DEFUN FACT (X) (IF (<= X 1) 1 (* X (FACT (1- X)))))
FACT
NIL
[6]> (fact 3)
6
[7]> (defvar *big* 1000)
*BIG*
[8]> (integer-length (fact *big*))
8530
...
[19]> (defmacro define (name value)
(if (listp name)
`(define ,(car name) (lambda ,(cdr name) ,value))
`(progn
(defparameter ,name ,value)
,(when (and (listp value) (eq 'lambda (car value)))
(list* 'defun name (second value) (cddr value)))
',name)))
DEFINE
[20]> (define f (lambda (x) (* x x)))
F
[21]> (define (g o x) (funcall o (funcall o x)))
G
[22]> (g f 2)
16
[23]> (f 2)
4
[24]> (list-packages-with-sources)
(#<PACKAGE IMAGE-BASED-COMMON-LISP> #<PACKAGE IMAGE-BASED-COMMON-LISP-USER>)
[27]> (save-sources "SCRATCH.LISP" :package *package*)
[28]> (with-open-file (src "SCRATCH.LISP")
(loop :for line = (read-line src nil nil) :while line :do (princ line) (terpri)))
(IN-PACKAGE "IMAGE-BASED-COMMON-LISP-USER")
(DEFUN FACT (X) (IF (<= X 1) 1 (* X (FACT (1- X)))))
(DEFVAR *BIG* 1000)
(DEFMACRO DEFINE (NAME VALUE)
(IF (LISTP NAME) `(DEFINE ,(CAR NAME) (LAMBDA ,(CDR NAME) ,VALUE))
`(PROGN (DEFPARAMETER ,NAME ,VALUE)
,(WHEN (AND (LISTP VALUE) (EQ 'LAMBDA (CAR VALUE)))
(LIST* 'DEFUN NAME (SECOND VALUE) (CDDR VALUE)))
',NAME)))
(DEFPARAMETER F (LAMBDA (X) (* X X)))
(DEFUN F (X) (* X X))
(DEFPARAMETER G (LAMBDA (O X) (FUNCALL O (FUNCALL O X))))
(DEFUN G (O X) (FUNCALL O (FUNCALL O X)))
NIL
[29]> (save-image "fact-and-define" :executable t :norc t)
[30]> (ext:quit)
Bye.
Process inferior-lisp finished
Then you can either:
% ./fact-and-define
i i i i i i i ooooo o ooooooo ooooo ooooo
I I I I I I I 8 8 8 8 8 o 8 8
I \ `+' / I 8 8 8 8 8 8
\ `-+-' / 8 8 8 ooooo 8oooo
`-__|__-' 8 8 8 8 8
| 8 o 8 8 o 8 8
------+------ ooooo 8oooooo ooo8ooo ooooo 8
Copyright (c) Bruno Haible, Michael Stoll 1992, 1993
Copyright (c) Bruno Haible, Marcus Daniels 1994-1997
Copyright (c) Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998
Copyright (c) Bruno Haible, Sam Steingold 1999-2000
Copyright (c) Sam Steingold, Bruno Haible 2001-2006
[1]> (get-source 'function 'fact)
(DEFUN FACT (X) (IF (<= X 1) 1 (* X (FACT (1- X))))) ;
T
[2]> (get-source 'function 'define)
(DEFMACRO DEFINE (NAME VALUE)
(IF (LISTP NAME) `(DEFINE ,(CAR NAME) (LAMBDA ,(CDR NAME) ,VALUE))
`(PROGN (DEFPARAMETER ,NAME ,VALUE)
,(WHEN (AND (LISTP VALUE) (EQ 'LAMBDA (CAR VALUE)))
(LIST* 'DEFUN NAME (SECOND VALUE) (CDDR VALUE)))
',NAME))) ;
T
[3]> (get-source 'function '*big*)
NIL ;
NIL
[4]> (ext:quit)
Bye.
Or:
% ./ibcl
i i i i i i i ooooo o ooooooo ooooo ooooo
I I I I I I I 8 8 8 8 8 o 8 8
I \ `+' / I 8 8 8 8 8 8
\ `-+-' / 8 8 8 ooooo 8oooo
`-__|__-' 8 8 8 8 8
| 8 o 8 8 o 8 8
------+------ ooooo 8oooooo ooo8ooo ooooo 8
Copyright (c) Bruno Haible, Michael Stoll 1992, 1993
Copyright (c) Bruno Haible, Marcus Daniels 1994-1997
Copyright (c) Bruno Haible, Pierpaolo Bernardi, Sam Steingold 1998
Copyright (c) Bruno Haible, Sam Steingold 1999-2000
Copyright (c) Sam Steingold, Bruno Haible 2001-2006
;; Loading file /home/pjb/.clisprc.lisp ...
;; Reading ASDF packages from /home/pjb/asdf-central-registry.data...
; loading system definition from /usr/local/share/lisp/packages/net/sourceforge/cclan/asdf-install/asdf-install.asd into #<PACKAGE ASDF4433>
; registering #<SYSTEM ASDF-INSTALL #x2049B826> as ASDF-INSTALL
0 errors, 0 warnings
[1]> (load"SCRATCH.LISP")
;; Loading file SCRATCH.LISP ...
;; Loaded file SCRATCH.LISP
T
[2]> (get-source 'function 'fact)
(DEFUN FACT (X) (IF (<= X 1) 1 (* X (FACT (1- X))))) ;
T
[3]> (get-source 'function '*big*)
NIL ;
NIL
[4]> (get-source 'variable '*big*)
(DEFVAR *BIG* 1000) ;
T
[5]> (ext:quit)
Bye.
Here are the files and the command to create ibcl:
clisp -ansi -norc -i ibcl-bootstrap.lisp -p "IBCL"
----(ibcl-bootstrap.lisp)----------------------------------------------------
;;;; IBCL Bootstrap
(in-package "COMMON-LISP-USER")
(load (merge-pathnames #P"ibcl.lisp" *load-pathname*))
(in-package "COMMON-LISP")
(delete-package "COMMON-LISP-USER")
(defpackage "COMMON-LISP-USER"
(:nicknames "CL-USER")
(:use "IBCL"))
(in-package "IMAGE-BASED-COMMON-LISP-USER")
(ext:saveinitmem "ibcl" :start-package "IBCL-USER" :executable t)
(ext:quit)
-----------------------------------------------------------------------------
----(ibcl.lisp)---------------------------------------------------------------
;;;; Image Based Common Lisp
;;;;**************************************************************************
;;;;FILE: ibcl.lisp
;;;;LANGUAGE: Common-Lisp
;;;;SYSTEM: Common-Lisp
;;;;USER-INTERFACE: NONE
;;;;DESCRIPTION
;;;;
;;;; The package IBCL exports the same symbols as COMMON-LISP, but for
;;;; some of the functions of macros modified to track of the source
;;;; of the definitions and to be able to edit them from the image,
;;;; and to save them in files.
;;;;
;;;; The package IBCL-USER is a virgin package using IBCL instead of CL.
;;;;
;;;; One can work at the REPL, define variables with
;;;; DEFCONSTANT, DEFVAR, DEFPARAMETER, macros with DEFMACRO,
;;;; and functions with DEFUN, edit macro and function definitions
;;;; with ED, and save the image with SAVE-IMAGE.
;;;;
;;;; The function LIST-PACKAGES-WITH-SOURCES returns a list of packages
;;;; where some of these variables or functions are defined.
;;;; The function GET-SOURCE returns the source form of the given
;;;; variable or function.
;;;; The function SAVE-SOURCES saves the definitions in a package,
;;;; or all the definitions to a file or stream.
;;;;
;;;;AUTHORS
;;;; <PJB> Pascal Bourguignon <p...@informatimago.com>
;;;;MODIFICATIONS
;;;; 2006-05-04 <PJB> Added this header. Augmented.
;;;;BUGS
;;;; Missing some def* macros, like define-symbol-macro,
;;;; defclass, defconditions, defpackage, defmethod, defgeneric, etc.
;;;; Missing some functions, like make-package, rename-package, etc.
;;;; See also MOP functions.
;;;;LEGAL
;;;; GPL
;;;;
;;;; Copyright Pascal Bourguignon 2006 - 2006
;;;;
;;;; This program is free software; you can redistribute it and/or
;;;; modify it under the terms of the GNU General Public License
;;;; as published by the Free Software Foundation; either version
;;;; 2 of the License, or (at your option) any later version.
;;;;
;;;; This program is distributed in the hope that it will be
;;;; useful, but WITHOUT ANY WARRANTY; without even the implied
;;;; warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
;;;; PURPOSE. See the GNU General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU General Public
;;;; License along with this program; if not, write to the Free
;;;; Software Foundation, Inc., 59 Temple Place, Suite 330,
;;;; Boston, MA 02111-1307 USA
;;;;**************************************************************************
(cl:defpackage "IMAGE-BASED-COMMON-LISP"
(:nicknames "IBCL")
(:use "COMMON-LISP")
;; We some symbols from the package #+clisp "EXT" too.
(:shadow "DEFPACKAGE"
"DEFCONSTANT" "DEFVAR" "DEFPARAMETER"
"DEFUN" "DEFMACRO" "LAMBDA"
"ED" "DELETE-PACKAGE"
#| TODO: Add define-symbol-macro, defclass, define-condition, etc...
make-package, etc...
|#)
#| See exports at the end. |#)
(in-package "IMAGE-BASED-COMMON-LISP")
(cl:defparameter *map* (make-hash-table)
"Maps packages to (cons definitions order)")
(cl:defun delete-package (package-designator)
(remhash (find-package package-designator) *map*)
(cl:delete-package package-designator))
(cl:defmacro define-package-attribute
(name (package-designator record &optional (value nil value-p)) &body body)
(let ((pack (gensym)))
`(cl:defun ,name (,@(when value-p `(,value)) ,package-designator)
(let* ((,pack (find-package ,package-designator))
(,record (gethash ,pack *map*)))
(if ,record
(progn ,@body)
(let ((,record (cons (make-hash-table :test (function equal)) '())))
(setf (gethash ,pack *map*) ,record)
,@body))))))
(define-package-attribute definitions (package-designator record) (car record))
(define-package-attribute order (package-designator record) (cdr record))
(define-package-attribute (setf order) (package-designator record value)
(setf (cdr record) value))
#||
(cl:defun definitions (package-designator)
(let ((record (gethash (find-package package-designator) *map*)))
(if record
(car record)
(let ((record (cons (make-hash-table :test (function equal)) '())))
(setf (gethash (find-package package-designator) *map*) record)
(car record)))))
(cl:defun order (package-designator)
(let ((record (gethash (find-package package-designator) *map*)))
(if record
(cdr record)
(let ((record (cons (make-hash-table :test (function equal)) '())))
(setf (gethash (find-package package-designator) *map*) record)
(cdr record)))))
(cl:defun (setf order) (value package-designator)
(let ((record (gethash (find-package package-designator) *map*)))
(if record
(setf (cdr record) value)
(let ((record (cons (make-hash-table :test (function equal)) '())))
(setf (gethash (find-package package-designator) *map*) record)
(setf (cdr record) value)))))
||#
(cl:defmacro push-on-top (value place &key (test (function eql))
&environment env)
(multiple-value-bind (vars vals store-vars writer-form reader-form)
(get-setf-expansion place env)
(let ((vvalue (gensym)))
`(let* ((,vvalue ,value)
,@(mapcar (function list) vars vals)
(,(car store-vars) (cons ,vvalue (delete ,vvalue ,reader-form
:test ,test))))
,writer-form))))
(cl:defmacro defconstant (name value
&optional (documentation nil documentation-p))
(let ((key (gensym))
(def (gensym)))
`(let ((,key (cons 'variable ',name))
(,def (definitions ',(symbol-package name))))
(setf (gethash ,key ,def)
(list 'defconstant ',name ',value
,@(when documentation-p `(',documentation))))
(pushnew ,key (order ,(symbol-package name)) :test (function equal))
(cl:defconstant ,name ,value
,@(when documentation-p `(,documentation))))))
(cl:defmacro defvar (name &optional (value nil value-p)
(documentation nil documentation-p))
(let ((key (gensym))
(def (gensym)))
`(let ((,key (cons 'variable ',name))
(,def (definitions ,(symbol-package name))))
(setf (gethash ,key ,def)
(list 'defvar ',name
,@ (when value-p
`(',value ,@(when documentation-p `(',documentation))))))
(pushnew ,key (order ,(symbol-package name)) :test (function equal))
(cl:defvar ,name
,@ (when value-p
`(,value ,@(when documentation-p `(,documentation))))))))
(cl:defmacro defparameter (name value
&optional (documentation nil documentation-p))
(let ((key (gensym))
(def (gensym)))
`(let ((,key (cons 'variable ',name))
(,def (definitions ,(symbol-package name))))
(setf (gethash ,key ,def)
(list 'defparameter ',name ',value
,@(when documentation-p `(',documentation))))
(pushnew ,key (order ,(symbol-package name)) :test (function equal))
(cl:defparameter ,name ,value
,@(when documentation-p `(,documentation))))))
;; Note: we compile the functions immediately, which may not be the
;; normal behavior when an interpreter is available, to
(cl:defmacro defmacro (name args &body body)
(let ((key (gensym))
(def (gensym)))
`(let ((,key (cons 'function ',name))
(,def (definitions ,(symbol-package name))))
(cl:defmacro ,name ,args ,@body)
(eval-when (:execute)
(compile ',name))
(unless (compiled-function-p (macro-function ',name))
)
(setf (gethash ,key ,def) '(defmacro ,name ,args ,@body)
(gethash (cons 'function (fdefinition ',name)) ,def)
(gethash ,key ,def))
(pushnew ,key (order ,(symbol-package name)) :test (function equal))
',name)
))
(cl:defmacro defun (name args &body body)
(let ((key (gensym))
(def (gensym)))
`(let ((,key (cons 'function ',name))
(,def (definitions ,(symbol-package name))))
(cl:defun ,name ,args ,@body)
(eval-when (:execute)
(compile ',name))
(unless (compiled-function-p (function ,name))
)
(setf (gethash ,key ,def) '(defun ,name ,args ,@body)
(gethash (cons 'function (fdefinition ',name)) ,def)
(gethash ,key ,def))
(pushnew ,key (order ,(symbol-package name)) :test (function equal))
',name)))
(cl:defmacro lambda (args &body body)
`(cl:function (cl:lambda ,args ,@body)))
;; (cl:defmacro lambda (args &body body)
;; (let ((key (gensym))
;; (def (gensym))
;; (fun (gensym)))
;; `(let ((,key (cons 'function ',fun))
;; (,def (definitions *package*))
;; (,fun (compile ',nam (cl:lambda ,args ,@body))))
;; (setf (gethash ,key ,def) '(lambda ,args ,@body)
;; (gethash (cons 'function ,fun) ,def)
;; (gethash ,key ,def))
;; ,fun)))
(defmacro defpackage (name &rest options)
`(cl:defpackage ,name
,@(mapcar
(lambda (option)
(if (listp option)
(case (first option)
((:use)
(substitute "IBCL" "COMMON-LISP"
(substitute "IBCL" "CL" option)))
((:shadowing-import-from :import-from)
(if (member (string (second option))
'("CL" "COMMON-LISP")
:test (function string=))
(list* (first option)
"IBCL"
(cddr option))
option))
(otherwise option))))
options)))
(cl:defun list-packages-with-sources ()
(let ((result '()))
(maphash (lambda (k v) (declare (ignore v)) (push k result)) *map*)
result))
(cl:defun get-source (kind name)
;; TODO: with symbol-package we cannot find fdefinitions...
(gethash (cons kind name) (definitions (symbol-package name))))
(cl:defun save-sources (path-or-stream &key package)
(labels ((save-one-package (out package)
(let ((*print-readably* nil)
(*package* (find-package package)))
(loop
:with def = (definitions package)
:with processed = (make-hash-table :test (function equal))
:for item :in (reverse (order package))
:initially (pprint `(in-package ,(package-name package)) out)
:unless (gethash item processed)
:do (progn
(setf (gethash item processed) t)
(pprint (gethash item def) out)))))
(save-packages (out package)
(if package
(save-one-package out package)
(dolist (package (list-packages-with-sources))
(save-one-package out package)))))
(if (streamp path-or-stream)
(save-packages path-or-stream package)
(with-open-file (out path-or-stream
:direction :output :if-exists :Supersede
:if-does-not-exist :create)
(save-packages out package))))
(values))
(cl:defun save-image (&rest args)
#+clisp
(labels ((key-present-p (key plist)
(and (not (null plist))
(or (eq key (car plist)) (key-present-p key (cddr plist))))))
(let* ((keys (rest args)))
(unless (key-present-p :start-package keys)
(setf (getf keys :start-package) (find-package "IBCL-USER")))
(unless (key-present-p :norc keys)
(setf (getf keys :norc) t))
(apply (function ext:saveinitmem)
(first args)
keys)))
#-clisp (error "I don't know how to save an image in ~A"
(lisp-implementation-type))
(values))
(cl:defun make-temporary-pathname ()
"Generate a rather unlikely filename."
(loop
:for path = (make-pathname :name (format nil "~36R" (get-universal-time))
:type "LISP"
:case :COMMON
:defaults (user-homedir-pathname))
:while (probe-file path)
:finally (return path)))
(cl:defmacro handling-errors (&body body)
`(HANDLER-CASE (progn ,@body)
(simple-condition
(ERR)
(format *error-output* "~&~A: ~%" (class-name (class-of err)))
(apply (function format) *error-output*
(simple-condition-format-control err)
(simple-condition-format-arguments err))
(format *error-output* "~&"))
(condition
(ERR)
(format *error-output* "~&~A: ~% ~S~%"
(class-name (class-of err)) err))))
(cl:defun ed (&optional x)
(typecase x
(null (cl:ed)) ; edit whatever.
((or pathname string) (cl:ed x)) ; edit an external file.
(otherwise
(let ((def (get-source 'function x)))
(if def
(let ((path (make-temporary-pathname))
;; TODO: with symbol-package we cannot find fdefinitions...
(*package* (symbol-package x)))
(unwind-protect
(progn
(with-open-file (out path
:direction :output
:if-does-not-exist :create
:if-exists :error)
(pprint def out))
(cl:ed path)
(handling-errors
(with-open-file (in path)
(loop
:for form = (read in nil in)
:until (eq form in)
:do
(when *load-verbose* (print form *trace-output*))
(print (eval form))))))
(delete-file path)))
(cl:ed x)))))) ; try to edit the function anyways.
(cl:defun repl ()
(do ((+eof+ (gensym))
(hist 1 (1+ hist)))
(nil)
(format t "~%~A[~D]> " (package-name *package*) hist)
(handling-errors
(setf +++ ++ ++ + + - - (read *standard-input* nil +eof+))
(when (or (eq - +eof+)
(member - '((quit)(exit)(continue)) :test (function equal)))
(return-from repl))
(setf /// // // / / (multiple-value-list (eval -)))
(setf *** ** ** * * (first /))
(format t "~& --> ~{~S~^ ;~% ~}~%" /))))
;; We must pass the symbol in a list to export CL:NIL.
(export (mapcar (lambda (name) (intern name "IBCL"))
(append '("SAVE-IMAGE" "SAVE-SOURCES"
"GET-SOURCE" "LIST-PACKAGES-WITH-SOURCES")
(let ((symbols '()))
(do-external-symbols (sym "COMMON-LISP")
(push (string sym) symbols))
symbols))))
(let ((*error-output* (make-broadcast-stream)))
(defpackage "IMAGE-BASED-COMMON-LISP-USER"
(:nicknames "IBCL-USER")
(:use "IMAGE-BASED-COMMON-LISP")))
(in-package "IBCL-USER")
------------------------------------------------------------------------------
--
__Pascal Bourguignon__ http://www.informatimago.com/
ATTENTION: Despite any other listing of product contents found
herein, the consumer is advised that, in actuality, this product
consists of 99.9999999999% empty space.
On Fri, 26 May 2006 16:20:54 +0200, Pascal Bourguignon wrote:
> BobF <rNfOrS...@charter.net> writes:
>
>> OK, so I get lispbox installed with clisp 2.37 ... it's all good
>>
>> So, now I'm following along with the first practical from "Practical Common
>> Lisp". It all works great AND I'm understanding what I'm doing!
>>
>> However, as I'm building up the functionality interactively via REPL, how
>> the heck do I save what I've accumulated in REPL to a .lisp file for later
>> use/modification?
>>
>> I ended up saving the REPL buffer, but then I have to edit out the prompts,
>> commands and output to get a clean .lisp file. There must be an *easier*
>> way to do this.
>
> You could prepare an image-based-common-lisp image with the following
> command and two files.
>
> % ibcl
>
<<SNIP for brevity>>
> I'm using the split window approach. I'm just looking for a quick &
> easy way to move code back and forth between windows.
Typically I type anything valuable into a (possibly) file-based buffer
and use `M-C-x' or `C-x e' to evaluate it, and only type into the REPL
for throwaway forms such as invoking test functions or checking values
of special variables. Even then, I tend to keep my test-invoking forms
with the "real code", guarded by "#+test".
(defun some-important-function (...)
...)
#+test
(some-important-function 1 2 'foo ...)
In short, don't bother investing too much effort with the REPL when
you already have the ability to evaluate arbitrary forms in any
buffer.
--
Steven E. Harris
> Typically I type anything valuable into a (possibly) file-based buffer
> and use `M-C-x' or `C-x e' to evaluate it, and only type into the REPL
> for throwaway forms such as invoking test functions or checking values
> of special variables. Even then, I tend to keep my test-invoking forms
> with the "real code", guarded by "#+test".
>
> (defun some-important-function (...)
> ...)
>
> #+test
> (some-important-function 1 2 'foo ...)
>
>
> In short, don't bother investing too much effort with the REPL when
> you already have the ability to evaluate arbitrary forms in any
> buffer.
I am having difficulty employing this approach in emacs+slime.
When I evaluate a form in a file buffer, the result is printed in
the mini-buffer and it dissapears before I can copy the result.
And * does not hold the result.
Using the various 'send' commands in a lisp file buffer set to
slime-mode, you don't need to cut and paste to move code from that
buffer to the repl. For going the other direction, cut and paste will
probably suffice to start with, but therer was a post to this group a
couple of months ago where someone posted a bit of elisp which would
make it easier to grab the last block of code from the history in the
repl and paste it into another file. This is probably what you want in
the long run, but I'd suggest sticking with what you have until your
more comfortable with emacs as it is quite likely the posted code may
need some 'tweaking' (I'm not saying the original poster was a poor
coder or anything, but often code posted to a group has had only
minimal testing and requires additional work - its more often a proof
of concept rather than a finished job. Adding code like this before
you can understand how it works can easily create a flakey environment
that is difficult to get stable again)
HTH
Sounds like your in emacs lisp mode in the file buffer and not emacs
slime mode. When in the file buffer type
M-x slime-mode
> > I am having difficulty employing this approach in emacs+slime.
> > When I evaluate a form in a file buffer, the result is printed in
> > the mini-buffer and it dissapears before I can copy the result.
> > And * does not hold the result.
>
> Sounds like your in emacs lisp mode in the file buffer and not emacs
> slime mode. When in the file buffer type
>
> M-x slime-mode
The buffer is in the slime lisp mode. Evaluating a lisp form
produces a correct result. Only that the result is printed
in a mini buffer instead of REPL.
For instance, by evaluating (+ 23), I get:
"=> 23 (#x17, #o27, #b10111)"
printed at the bottom of a emacs window and I cannot
move a caret to that area.
Your right. I must have remembered it wrong. There are two possible
ways around this I can think of
1. Wrap things in a prin1 or princ i.e
(prin1 (+ 21))
or use the pretty print option C-c C-p, which will put the result in
the SLIME describe buffer which you can then cut and paste or
whatever.
(defun slime-eval-defun-in-repl ()
(interactive)
(slime-repl-send-string (slime-defun-at-point))
(slime-eval-with-transcript `(swank:interactive-eval "CL:*")
(lambda (result)
(slime-message "%s" result))))
this will eval the current toplevel form (if you want something else
change the class to slime-defun-at-point), send it to the repl and
then display the result in the minibuffer. if you jump back to the
repl you'll have the result and you can use *, ** or the
presenentation magick or the inspector.
this still has some issues (you don't the see the form, only the
result; package confusion can happen; sometimes the repl buffer opens
up; etc.) but it should be a good start.
--
-Marco
Ring the bells that still can ring.
Forget the perfect offering.
There is a crack in everything.
That's how the light gets in.
-Leonard Cohen
You can preface the C-x C-e evaluation with C-u and the result
will be printed at point.
Regards,
Patrick
------------------------------------------------------------------------
S P Engineering, Inc. | The experts in large scale distributed OO
| systems design and implementation.
p...@spe.com | (C++, Java, Common Lisp, Jini, CORBA, UML)
I hardly ever type things into the REPL either - I just use (possibly
scratch) buffers.
M-x slime-ensure-typeout-frame
solves the problem with evaluated forms disappearing - it creates
another emacs frame into which results are put instead of the mini
buffer. Very useful.
-- David
---- Forwarded Usenet-message ----
From:
Newsgroups: comp.lang.lisp
Subject: Re: getting started
Date: Fri, 26 May 2006 00:07:11 +0200
URL: news://
I'll give you a hint.
You can send funtion code from a lisp file directly to
the interpreter.
1. Create a lisp file (ex test.lisp) <ctrl>-x-f
2 write your fuinction the buffer
3. at the end of the function type <ctrl>-c-c
4. switch to the interpreter
<ctrl>-x-b lisp-shell-buffer if buffer not visible
<ctrl>-x-o switches to the other buffer if it is visible
Also in a lisp buffer type <crtl>-h-m
That gives you the keystrokes available in that mode.
(<ctrl>-x-k kills the buffer when you are finished
For the comands for compiling a buffer:
http://common-lisp.net/project/slime/doc/html/slime_16.html#SEC16
Better still read the whole manual.
http://common-lisp.net/project/slime/doc/html/slime.html
--
Using Opera's revolutionary e-mail client: http://www.opera.com/mail/
Thank you very much. It works nicely.
(now I need to figure out how to assign short cut keys for it.
knowledges re: emacs never seem to stick to my brain. strange.
emacs hates me.)
Thanks to everybody for your responses. I have more than enough to go on
now.