Обновлен, более простой ответ:
Мы можем оценить формы в REPL в пространстве имен текущего файла, введя это пространство имен в REPL, оценив эти формы, а затем повторно введя нашоригинальное пространство имен.Кажется, что проще всего сделать это, обернув эти формы функциями для ввода пространства имен текущего файла (до) и повторного ввода исходного пространства имен (после), а затем отправив все это в существующий код режима Racket для оценки форм вРЕПЛ.
Мы можем сделать это, построив строку наших упакованных команд, записав ее во временный буфер, отметив весь буфер как наш регион, а затем отправив его в racket-send-region
.
(defun my-racket-current-namespace-wrapped-commands (buffer-file-string commands)
"generate string containing commands wrapped with Racket functions to enter
the current-namespace and then exit it upon finishing"
(concat "(require (only-in racket/enter enter!))"
"(enter! (file "
buffer-file-string
"))"
commands
"(enter! #f)"))
(defun my-racket--send-wrapped-current-namespace (commands)
"sends wrapped form of commands to racket-send-region function via a temporary buffer"
(let ((buffer-file-string (prin1-to-string buffer-file-name)))
(with-temp-buffer
(insert
(my-racket-current-namespace-wrapped-commands buffer-file-string commands))
(mark-whole-buffer)
(racket-send-region (point-min) (point-max)))))
(defun my-racket-send-region-current-namespace (start end)
"send region to REPL in current namespace"
(interactive "r")
(unless (region-active-p)
(user-error "No region"))
(let ((commands (buffer-substring (region-beginning) (region-end))))
(my-racket--send-wrapped-current-namespace commands)))
(defun my-racket-send-last-sexp-current-namespace ()
"send last sexp to REPL in current namespace"
(interactive)
(let ((commands (buffer-substring (my-racket--repl-last-sexp-start)
(point))))
(my-racket--send-wrapped-current-namespace commands)))
(defun my-racket--repl-last-sexp-start ()
"get start point of last-sexp
permanent (and slightly simplified) copy of racket mode's last-sexp-start private function"
(save-excursion
(progn
(backward-sexp)
(if (save-match-data (looking-at "#;"))
(+ (point) 2)
(point)))))
Эти функции в основном должны быть независимыми от версии - они зависят только от racket-send-buffer
(который, вероятно, останется в будущих версиях).
Редактировать 1: (Примечание: это не похожеработать как есть для более новых версий Racket-mode. Это работало с выпуском 01 апреля 2018 года, но новые версии, по-видимому, реорганизовали некоторые внутренние компоненты, на которые он опирался. Почти во всех случаях предпочтительным является приведенный выше код.)
Извините, я считаю, что изначально неправильно понял вопрос.Похоже, вы имеете в виду выполнение команды прямо из view.rkt без необходимости вручную изменять пространство имен в REPL.Я не видел ни одной встроенной функциональности в режиме ракетки, которая бы это делала, но не так уж сложно написать обертку Elisp вокруг этого процесса.Следующий импорт в enter!
, переключает в пространство имен файла текущего буфера, отправляет код в область, а затем переключается обратно в исходное пространство имен.Используемый код очень похож на тот, который используется в режиме ракетки для racket-send-region
и racket-send-last-sexp
.
(defun my-racket-send-region-current-namespace (start end)
"Send the current region to the Racket REPL as that namespace"
(interactive "r")
(when (and start end)
(racket-repl t)
(racket--repl-forget-errors)
(let ((proc (racket--get-repl-buffer-process)))
(with-racket-repl-buffer
(save-excursion
(goto-char (process-mark proc))
(insert ?\n)
(set-marker (process-mark proc) (point))))
(comint-send-string proc "(require (only-in racket/enter enter!))")
(comint-send-string proc
(concat "(enter! (file "
(prin1-to-string buffer-file-name)
"))"))
(comint-send-string proc "\n"))
(racket--repl-show-and-move-to-end)
(racket--send-region-to-repl start end)
(let ((proc (racket--get-repl-buffer-process)))
(with-racket-repl-buffer
(save-excursion
(goto-char (process-mark proc))
(insert ?\n)
(set-marker (process-mark proc) (point))))
(comint-send-string proc "(enter! #f)")
(comint-send-string proc "\n"))))
(defun my-racket-send-last-sexp-current-namespace ()
(interactive)
(my-racket-send-region-current-namespace
(save-excursion
(backward-sexp)
(if (save-match-data (looking-at "#;"))
(+ (point) 2)
(point)))
(point)))
Обратите внимание, что если вы используете это часто, эта функция может использовать больше проверки ошибок (например,импорт require/enter
закроет любое предыдущее определение enter!
).
Я также сохранил исходный текст ниже о том, как вручную переключать пространства имен в REPL, если это поможет.
Вы можете использовать функцию enter!
в модуле racket/enter
для переключения пространств имен для изменения определений в пространстве имен другого файла.
После вызова racket-run
в web.rkt,Вы можете сделать следующее в REPL:
(display-default-view) ;; output is "Hello world"
(require racket/enter)
(enter! "view.rkt") ;; change namespace to view.rkt
(define default-text "Hi")
(enter! #f) ;; return to original namespace
(display-default-view) ;; output is "Hi world"
См. документацию Racket для получения более подробной информации о загрузке интерактивного модуля .