4

Я обнаружил, что использую мой основной сеанс Emacs (CocoaEmacs в OSX) для редактирования командной строки bash. Для этого мой РЕДАКТОР установлен на emacsclient . Затем я редактирую строку в Emacs, сохраняю и покидаю этот буфер - обычно используя "C-x #" который выполняется (server-edit) .

Проблема в том, что иногда я нахожусь в процессе редактирования строки, и я понимаю, что не хочу на самом деле выполнить строку (сожаление наступает). Проблема в том, что bash определяет, выполнять ли строку или нет, основываясь на состоянии возврата.

Я хотел бы, чтобы у меня было два варианта.

  1. Если я нажму "C-x #" сохраните буфер и верните код выхода 0 (то есть, я закончил редактирование и готов к bash, чтобы покончить с этим).

  2. Если я уничтожу буфер, не сохраняйте буфер, не уничтожайте его и не возвращайте ненулевой код завершения. Я бы даже не возражал, если бы мне пришлось нажимать на альтернативное связывание.

Одно частичное решение - просто прокомментировать строку. Я не рассматриваю это как вариант для меня, потому что обычно я редактирую командную строку в Emacs, потому что я работаю над многострочным программированием.

2 ответа2

4

В относительно текущих версиях Emacs (например, в моей копии Emacs 24.2, но не в дистрибутиве emacs 22.1 для OS X) вы можете написать код Elisp, который отправит команду emacsclient, сообщающую ему о выходе с состоянием выхода из ошибки.

Это проще, чем кажется.

Существует локальная переменная server-buffer-clients , с клиентами, которые подключены к буферу. А функция server-send-string может использоваться для передачи команд в соответствии с server-process-filter .

Например:

(server-send-string (car server-buffer-clients) "-error die")

вызывает (один из) emacsclient (s), связанный с буфером, для немедленной выдачи текста

*ERROR*: die

и затем выйдите с кодом выхода 1.


Итак, довольно просто определить интерактивную функцию, которую вы могли бы вызывать из самого emacs, чтобы уничтожить emacsclients:

(defun tell-emacsclients-for-buffer-to-die ()
  "Sends error exit command to every client for the current buffer."
  (interactive)
  (dolist (proc server-buffer-clients)
    (server-send-string proc "-error die")))

С указанным выше в вашем файле .emacs (и достаточно актуальной версией Emacs) вы можете вызвать M-x tell-emacsclients-for-buffer-to-die чтобы заставить emacsclients завершить работу с состоянием ошибки. (И, конечно, вы можете связать эту функцию с соответствующей последовательностью альтернативных клавиш.)


сноска

В идеале можно было бы соединить вышеописанную функцию с хуком на функцию server-kill-buffer для достижения целевого числа (2.) в исходном вопросе. (То есть, уничтожение буфера без сохранения его через C-x # должно привести к тому же выходу ошибки из emacsclient.)

Однако мои попытки добавить это к kill-buffer-hook не увенчались успехом, потому что функция server-kill-buffer помещена в начало списка kill-buffer-hook после того, как были запущены перехватчики server-visit-hook , и поэтому функция server-kill-buffer по умолчанию будет запускаться первой. (Можно исправить исправление kill-buffer-hook позже, но я пока не уверен, куда поместить код, чтобы сделать это в поток управления Elisp.)

Обновление: Хорошо, вот действительно хакерский способ выполнить вышеупомянутое:

(defun kill-buffer-with-special-emacsclient-handling ()
  (interactive)
  (add-hook 'kill-buffer-hook 'tell-emacsclients-for-buffer-to-die nil t)
  (kill-buffer))

(global-set-key (kbd "C-x k") 'kill-buffer-with-special-emacsclient-handling)

Обновление 2: чуть более надежный вариант:

(defun kill-buffer-with-special-emacsclient-handling ()
  "Wrapper around kill-buffer that ensures tell-emacsclients-for-buffer-to-die is on the hooks"
  (interactive)
  (add-hook 'kill-buffer-hook 'tell-emacsclients-for-buffer-to-die nil t)
  (kill-buffer))

;; (global-set-key (kbd "C-x k") 'kill-buffer)

(defun install-emacsclient-wrapped-kill-buffer ()
  "Installs wrapped kill-buffer with special emacsclient handling.
Best not to install it unconditionally because the server is not
necessarily running."
  (interactive)
  (global-set-key (kbd "C-x k") 'kill-buffer-with-special-emacsclient-handling))

(add-hook 'server-switch-hook 'install-emacsclient-wrapped-kill-buffer)
1

Просто нажмите Ctrl+C в терминале, где вы запускаете bash. Это отменяет издание и подталкивает оригинальную линию к истории. Если вы не можете сделать это напрямую, потому что Emacs работает в том же терминале, убейте процесс emacsclient способом по вашему выбору.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .