[Openmcl-devel] Notes on emacs, slime and unicode on Mac

Takehiko Abe keke at gol.com
Thu Apr 19 13:24:46 UTC 2007

OpenMCL now supports unicode. But it is only half good if I don't have
an editor that can handle unicode.

Since emacs 21 that comes preinstalled on Mac OSX does not do
utf-8 very well, I decided to look for a new emacs. Finding the
one and configuring it for slime and openmcl was a hassle.

This note is a summary of what I went through.
I hope someone find this useful.
(but.. this is of no use if all you need is latin-1.)


Notes on emacs slime openmcl and unicode on Mac OS X.
[all done with Mac OS X 3.9 on PPC]


1. emacs
2. OpenMCL
3. Terminal.app
4. slime
5. misc (pbcopy)

1. emacs

To make a long story short, I settled on the emacs-unicode-2 branch of
emacs cvs.

I prefer emacs on a terminal emulator -- in this case Terminal.app.
One advantage (other than my pereference) is that unicode text rendering
is done by the Terminal.app, so you don't have to worry about fonts and
input methods.

Here's how I got the emacs source and built it:

$ cvs -z3 -d:pserver:anonymous at cvs.savannah.gnu.org:/cvsroot/emacs co \
  -r emacs-unicode-2 emacs
$ ./configure --without-carbon --without-x --disable-carbon-app \
    --without-xim --without-sound --without-pop 
$ make bootstrap

$ make install

2. OpenMCL pre 1.1

Put this in openmcl-init.lisp for slime-compile-file:

   (setq *default-file-character-encoding* :utf-8)

3. Terminal.app

Choose "Window Settings" from "Terminal" menu.  It opens "Terminal
Inspector" window.

There's a popup menu at the top of the inspector window.
>From the popup:

 - select "Emulation" and uncheck "Escape non-ASCII characters".
 - select "Display", and
   check "Wide glyphs for Japanese/Chinese/etc."
   check "Wide glyphs count as 2 columns".
   Select "Unicode (UTF-8)" for Character Encoding.

4. Slime

We need to redefines accept-connection and add find-external-format
in swank-openmcl.lisp (looks like the patch was added to slime cvs):

;; ---------------------------------------------------------------------

(in-package :swank-backend)

(defimplementation accept-connection (socket &key external-format
                                             buffering timeout)
  (declare (ignore buffering timeout
                   #-openmcl-unicode-strings external-format))
  ;; I know this is ugly. I tried (setf stream-external-format)
  ;; but it did not work. hence this hack.
  (when external-format
    (let ((keys (ccl::socket-keys socket)))
      (setf (getf keys :external-format) external-format
            (slot-value socket 'ccl::keys) keys)))
  (ccl:accept-connection socket :wait t))

(defvar *external-format-to-coding-system*
     "latin-1" "latin-1-unix" "iso-latin-1-unix" 
     "iso-8859-1" "iso-8859-1-unix")
    (:utf-8 "utf-8" "utf-8-unix")))

(defimplementation find-external-format (coding-system)
  (car (rassoc-if (lambda (x) (member coding-system x :test #'equal))

;; ---------------------------------------------------------------------

In .emacs :

;; standard stuff.
(setq inferior-lisp-program "/usr/bin/openmcl")
(add-to-list 'load-path path-to-slime)
(require 'slime)

;; tell slime we want utf-8
(setq slime-net-coding-system 'utf-8-unix)

;; I am not sure about this, but without it emacs put up a message
;; everytime I try to open some *.lisp file.
(setq enable-local-variables nil)

5. misc

/usr/bin/pbcopy is a handy command to copy text from emacs to other apps.

;; this is elisp not CL.
;; must be a better way. I am new to elisp.
(defun pbcopy (string &optional ignore)
  (let ((pr (start-process "pbcopy" nil "/usr/bin/pbcopy")))
    (process-send-string pr string)
    ;; why do we need to send eof twice?
    (process-send-eof pr)
    (process-send-eof pr)))

;; I don't know why this doesn't work.
(defun pbcopy (string &optional ignore)
   (format "/bin/echo -n %s | /usr/bin/pbcopy"

(setq interprogram-cut-function #'pbcopy)

But it turned out that pbcopy does not work with utf-8 (ascii chars are
fine) unless we set __CF_USER_TEXT_ENCODING.

In .bash_profile add the line:

    export __CF_USER_TEXT_ENCODING=0x1F5:0x8000100:0x8000100

I picked this up via google. And I don't know what
__CF_USER_TEXT_ENCODING really is. All I can see is that 0x8000100
happens to be the same as TextEncoding value for utf-8:

(#_CreateTextEncoding #$kTextEncodingUnicodeDefault

---> #x8000100 ("Unicode 4.0 UTF-8")

** end

"Not building a wall but making a brick."

More information about the Openmcl-devel mailing list