Common Lisp, Emacs и Slime: Automati c пакетный переключатель в repl после запуска - PullRequest
0 голосов
/ 18 марта 2020

Я пытаюсь написать функцию elisp, которая автоматически запускает slime, если он не запущен, а затем переключается на определенный пакет quicklisp после загрузки его в repl. Когда slime уже запущен, работает следующий код. Когда запускается slime fre sh, пакет 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)))))

( КСТАТИ: Мне известны подобные вопросы о стековом потоке, но приведенные ответы здесь не применимы)

1 Ответ

1 голос
/ 19 марта 2020

Я решил это: необходимо использовать '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))))
...