1. SLIMEのプロンプトとパッケージ名
以前に、SLIMEのREPLプロンプトを CL-USER> から * に変更しました。
しかし、しばらく使っていると、別のパッケージに切り替えたとき、今どこにいるかわからなくなる問題に気づきました。
そこで、デフォルトパッケージのときだけ * を表示し、それ以外はパッケージ名を出す方法に切り替えました。

1.1. COMMON-LISP-USER とは何か
Common Lispのデフォルトパッケージは COMMON-LISP-USER で、CL-USER はそのニックネームです。
このパッケージは COMMON-LISP パッケージを use した状態で用意されています。
標準シンボルである defun や car は、COMMON-LISPにあります。
自分でパッケージを定義するときに (:use :cl) を省くと、defun を書くのにも cl:defun と修飾が必要になります。
ライブラリ作者は、あえて(:use :cl) を省いて、意図せずに cl のシンボルを外部に公開しないようにすることもあります。
2. カスタマイズの方針
現在のパッケージ名は、slime-current-package 関数で取得できます。
SBCLでは "COMMON-LISP-USER" のように大文字の文字列が返ります。
これを使って、次のように振る舞いを分けます。
COMMON-LISP-USERのとき →*- それ以外のとき →
MY-PACKAGE>
処理系によっては挙動が異なる可能性があるので、M-: で (slime-current-package) を評価して確認しておくと安心です。CL-USER という文字列が返ってくる場合は、my-slime-prompt-string の比較対象を変更してください。
(with-eval-after-load 'slime-repl
(defun my-slime-prompt-string ()
(if (string= (slime-current-package) "COMMON-LISP-USER")
"* "
(concat (slime-current-package) "> ")))
(defun my-slime-insert-prompt-string (prompt)
(slime-propertize-region
'(face slime-repl-prompt-face
read-only t
slime-repl-prompt t
rear-nonsticky t
front-sticky (read-only)
inhibit-line-move-field-capture t
field output)
(insert-before-markers prompt)))
(defun my-slime-repl-insert-prompt ()
(goto-char slime-repl-input-start-mark)
(unless slime-repl-suppress-prompt
(slime-save-marker slime-output-start
(slime-save-marker slime-output-end
(unless (bolp)
(insert-before-markers "\n"))
(let ((prompt-start (point)))
(my-slime-insert-prompt-string (my-slime-prompt-string))
(set-marker slime-repl-prompt-start-mark prompt-start)
(setq buffer-undo-list nil)
prompt-start)))))
(advice-add 'slime-repl-insert-prompt :override #'my-slime-repl-insert-prompt))Code language: Lisp (lisp)
my-slime-prompt-stringは、パッケージ名を見てプロンプト文字列を返します。
ここだけ変えれば表示形式を自由に調整できます。my-slime-insert-prompt-stringはプロンプトにテキストプロパティを付けて挿入します。read-only tによってユーザーがプロンプト部分を誤って編集できないようになっています。slime-propertize-regionはSLIME側が用意しているユーティリティです。my-slime-repl-insert-promptは位置の制御とマーカーの保護を担います。slime-save-markerで出力の開始・終了マーカーを守りながら、上の2つの関数を呼びます。
最後に advice-add で :override を指定し、SLIMEの元の関数をこの実装で完全に置き換えます。
3. 動作確認
M-x slime でREPLを起動すると、プロンプトが * になっています。
別のパッケージに切り替えてみます。
* (defpackage :my-package
(:use :cl))
* (in-package :my-package)
MY-PACKAGE> Code language: Lisp (lisp)
COMMON-LISP-USER に戻すと * に戻ります。
MY-PACKAGE> (in-package :cl-user)
* Code language: Lisp (lisp)