ccl on MS-Windows uses MS-Windows physical pathnames.
emacs on cygwin has some flexibility, but mostly uses POSIX paths.
Happily, slime provides a mechanism to customize it's boot process.
When launched from cygwin, ccl uses C:\ for (USER-HOMEDIR-PATHNAME).
I guess cygwin resets the MS-Windows environment variable USERPROFILE.
But I wanted to use my rc files installed in cygwin. Each
implementation specific rc files load the same ~/rc/common.lisp file
that initialize my CL environment the uniformly on all CL
implementations. So I wrote the following C:\ccl-init.lisp :
------------------------------------------------------------------------
(let ((path (pathname (format nil "~A\\" (ccl:getenv "HOME")))))
(format t "C:\\ccl-init.lisp~%")
(setf (logical-pathname-translations "HOME")
(list (list "HOME:**;*.*.*"
(merge-pathnames
(make-pathname :name :wild :type :wild :version nil
:directory '(:relative :wild-inferiors)
:defaults path)
path nil))
(list "HOME:**;*.*"
(merge-pathnames
(make-pathname :name :wild :type :wild :version nil
:directory '(:relative :wild-inferiors)
:defaults path)
path nil))
(list "HOME:**;*"
(merge-pathnames
(make-pathname :name :wild :type nil :version nil
:directory '(:relative :wild-inferiors)
:defaults path)
path nil))
(list "HOME:**;"
(merge-pathnames
(make-pathname :name nil :type nil :version nil
:directory '(:relative :wild-inferiors)
:defaults path)
path nil))))
(let ((ccl-init (merge-pathnames #P"rc\\ccl-init.lisp" path nil)))
(format t "~A~%" ccl-init)
(load ccl-init)))
------------------------------------------------------------------------
But (USER-HOMEDIR-PATHNAME) still returns C:\ so I should avoid using it
in my rc files.
In ~/ccl-init.lisp (cygwin):
------------------------------------------------------------------------
(load (merge-pathnames
(make-pathname :directory '(:relative "RC") :name "COMMON" :type "LISP"
:case :common)
#+windows-target (pathname (format nil "~A\\" (ccl::getenv "HOME")))
#-windows-target (user-homedir-pathname)
nil))
------------------------------------------------------------------------
In ~/rc/common.lisp the only changes are defining a USER-PATHNAME
function to be used instead of USER-HOMEDIR-PATHNAME, and to use
MACHINE-INSTANCE instead of calling hostname with ASDF:RUN-SHELL-COMMAND
(it looks like ASDF:RUN-SHELL-COMMAND doesn't work on ccl on MS-Windows).
------------------------------------------------------------------------
(defun user-pathname ()
"On MS-Windows, it's not the USER-HOMEDIR-PATHNAME."
#+windows-target (pathname (format nil "~A\\" (ccl::getenv "HOME")))
#-windows-target (USER-HOMEDIR-PATHNAME))
(defun hostname ()
#-windows-target
(let ((outpath (make-pathname :name (format nil "hostname-~8,'0X" (random #x100000000))
:type "txt"
:case :local
:defaults (user-pathname))))
(unwind-protect
(let ((asdf::*verbose-out* t))
(asdf:run-shell-command
"( hostname --fqdn 2>/dev/null || hostname --long 2>/dev/null || hostname ) > ~A"
(namestring outpath))
(with-open-file (hostname outpath)
(read-line hostname)))
(delete-file outpath)))
#+windows-target (machine-instance))
------------------------------------------------------------------------
That allows one to launch ccl from cygwin using the same rc files as on
unix.
Now, to let slime boot swank in this implementation, we need to convert
the paths configured in emacs (as posix paths) to MS-Windows paths.
This is done thru a :init parameter to the slime-lisp-implementation.
In ~/.emacs:
------------------------------------------------------------------------
(push (list 'ccl-win-cygwin "/usr/local/bin/ccl" ; this is a script
; that calls the MS-Windows ccl.
:coding-system 'utf-8-unix
:init 'slime-init-ccl-win-cygwin)
slime-lisp-implementations)
(defun windoize-pathname (path)
(let ((home (expand-file-name "~/")))
(if (prefixp home path)
(format "HOME:%s" (substitute (character ";") (character "/") (subseq path (length home))))
(format "C:\\cygwin%s" (substitute (character "\\") (character "/") path)))))
(defun slime-init-ccl-win-cygwin (port-filename coding-system)
"Return a string to initialize Lisp."
(let ((loader (if (file-name-absolute-p slime-backend)
slime-backend
(concat slime-path slime-backend))))
;; Return a single form to avoid problems with buffered input.
(format "%S\n\n"
`(progn
(load ,(windoize-pathname (expand-file-name loader))
:verbose t)
(funcall (read-from-string "swank-loader:init"))
(funcall (read-from-string "swank:start-server")
,(windoize-pathname port-filename))))))
------------------------------------------------------------------------
And then, success! C-- M-x slime RET ccl-win-cygwin RET launches it:
; SLIME 2012-02-07
CL-USER> (list (lisp-implementation-type) (lisp-implementation-version)
(machine-type) (machine-version))
("Clozure Common Lisp" "Version 1.7-r14925M (WindowsX8664)" "x64" NIL)
CL-USER>
Now, on to compiling the deployment executables… ;-)
--
__Pascal Bourguignon__
http://www.informatimago.com/
A bad day in () is better than a good day in {}.