common-lisp - Common Lisp、Emacs 和 Slime:启动后 repl 中的自动包切换
问题描述
我正在尝试编写一个 elisp 函数,如果它没有运行,它会自动启动 slime,然后在将其加载到 repl 后更改为某个 quicklisp 包。当 slime 已经运行时,下面的代码可以工作。当 slime 重新开始时, quicklisp 包被 slime 加载,但是对 slime-eval-expression-in-repl 的调用似乎没有被执行。
(defun cm ()
"Start CM"
(interactive)
(cond ((slime-connected-p)
(slime-eval '(ql:quickload "cm"))
(slime-eval-expression-in-repl "(cm)")
(switch-to-buffer (slime-repl-buffer)))
(t
(slime)
(eval-after-load 'slime
(progn
(slime-eval '(ql:quickload "cm"))
(slime-eval-expression-in-repl "(cm)")
(switch-to-buffer (slime-repl-buffer)))))))
下面是改包的代码和 slime-eval-expression-in-repl 的函数定义(改编自 'slime-eval-last-expression-in repl)。我该如何解决这个问题?
常用的lisp函数:
(defun cm (&rest systems)
(flet ((cmcall (fn &rest args)
(apply (find-symbol (string fn) :cm) args))
(cmvar (var)
(symbol-value (find-symbol (string var) :cm))))
(setf *package* (find-package :cm))
(setf *readtable* (cmvar :*cm-readtable*))
;; add slime readtable mapping...
(let ((swank-pkg (find-package :swank)))
(when swank-pkg
(let ((sym (intern (symbol-name :*readtable-alist*) swank-pkg)))
(setf (symbol-value sym)
(cons (cons (symbol-name :cm) (cmvar :*cm-readtable*))
(symbol-value sym))))))
(let (#-sbcl (*trace-output* nil))
(dolist (s systems) (use-system s :verbose nil)))
(cmcall :cm-logo)))
这里是 slime-eval-expression-in-repl 的定义:
(defun slime-eval-expression-in-repl (expr)
"Evaluates expression in the Slime REPL.
Switches REPL to current package of the source buffer for the duration. If
used with a prefix argument (C-u), doesn't switch back afterwards."
(interactive "P")
(let ((buffer-name (buffer-name (current-buffer)))
(new-package (slime-current-package))
(old-package (slime-lisp-package))
(slime-repl-suppress-prompt t)
(yank-back nil))
(with-current-buffer (slime-output-buffer)
(unless (eq (current-buffer) (window-buffer))
(pop-to-buffer (current-buffer) t))
(goto-char (point-max))
;; Kill pending input in the REPL
(when (< (marker-position slime-repl-input-start-mark) (point))
(kill-region slime-repl-input-start-mark (point))
(setq yank-back t))
(unwind-protect
(progn
(insert-before-markers (format "\n;;; from %s\n" buffer-name))
(when new-package
(slime-repl-set-package new-package))
(let ((slime-repl-suppress-prompt nil))
(slime-repl-insert-prompt))
(insert expr)
(slime-repl-return)))
;; Put pending input back.
(when yank-back
(yank)))))
(顺便说一句:我知道关于stackoverflow的类似问题,但给出的答案似乎不适用于这里)
解决方案
我解决了:有必要使用 'slime-connected-hook 而不是 eval-after-load。此外,函数 slime-eval-expression-in-repl 已经作为 'slime-repl-send-string 存在。下面是我的解决方案。这有点棘手,因为我不想永久添加粘液连接钩。
(defun load-and-start-cm ()
(slime-eval '(ql:quickload "cm"))
(slime-repl-send-string "(cm)")
(switch-to-buffer (slime-repl-buffer)))
(defun load-and-start-cm-remove-hook ()
"after starting cm remove this hook from slime-connected-hook"
(load-and-start-cm)
(setq slime-connected-hook
(remove 'load-and-start-cm-remove-hook slime-connected-hook)))
(defun cm ()
"Start CM"
(interactive)
(message "entering cm function.")
(cond ((slime-connected-p)
(load-and-start-cm))
(t ;;; temporarily set slime-connected-hook to start cm
(unless (member 'load-and-start-cm slime-connected-hook)
(setq slime-connected-hook
(append slime-connected-hook '(load-and-start-cm-remove-hook))))
(slime))))
推荐阅读
- javascript - Firebase 文档快照字段
- laravel - VueJS中数组中的数据未填充到前端
- sql-server - SQL Management Studio 的 Windows 防火墙规则
- typescript - Kotlin 等效于省略 TypeScript 实用程序类型
- python - 在 Python 中将 00 年转换为 2000 年
- html - 如何在 HTML 中使用带有订单列表的表格?
- java - 在 Java 中使用 XPATH 和 DOM 更新空 XML 元素
- javascript - 媒体管道图,在javascript中运行?
- ios - 如何通过 StoreKit 服务器通知检测用户是否仍在享受促销优惠
- xmpp - 在openfire中如何创建自定义机器人