Como definir o status de saída para o emacsclient

4

Eu me encontrei usando minha sessão principal do Emacs (CocoaEmacs no OSX) para editar minha linha de comando bash. Para isso, tenho o meu EDITOR configurado para emacsclient . Então eu edito a linha no Emacs e salvo e fecho aquele buffer - normalmente usando "C-x #" que executa (server-edit) .

O problema é que algumas vezes eu estou no meio da edição de uma linha e percebo que não quero realmente executar a linha (o remorso se inicia). O problema é que o bash determina se deve executar a linha ou não com base no status de retorno.

O que eu gostaria é que haja duas opções para mim.

  1. Se eu clicar em "C-x #" , salve o buffer e retorne o código de saída 0 (ou seja, eu fiz minha edição e estou pronto para o bash para começar com isso).

  2. Se eu matar o buffer, não salve o buffer, mate-o e retorne um código de saída diferente de zero. Eu nem me importaria se tivesse que acertar uma ligação alternativa.

Uma solução parcial é apenas para comentar a linha. Eu não vejo isso como uma opção para mim, já que normalmente eu estou editando uma linha de comando no Emacs é que estou trabalhando em uma coisa de várias linhas.

    
por milkypostman 09.06.2011 / 20:31

2 respostas

4

Em versões relativamente atuais do Emacs (por exemplo, na minha cópia do Emacs 24.2, mas não na distribuição do emacs 22.1 do OS X), você pode escrever código Elisp que enviará um comando para o emacsclient dizendo para sair com uma saída de erro status.

Isso é mais fácil do que parece.

Existe uma variável local do buffer, server-buffer-clients , com os clientes que estão conectados ao buffer. E a função server-send-string pode ser usada para comunicar comandos seguindo o protocolo server-process-filter .

Por exemplo:

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

faz com que (um dos) emacsclient (s) associados ao buffer publiquem imediatamente o texto

*ERROR*: die

e saia com o código de saída 1.

Portanto, é muito fácil definir uma função interativa que você poderia chamar do próprio emacs para eliminar os 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")))

Com o acima em seu arquivo .emacs (e uma versão suficientemente atual do Emacs), você pode invocar M-x tell-emacsclients-for-buffer-to-die para fazer o emacsclients sair com o status de erro. (E, claro, você poderia vincular essa função a uma sequência de teclas alternativa apropriada.)

Nota de rodapé

O ideal seria, então, acoplar a função acima com um gancho na função server-kill-buffer para atingir o número da meta (2.) na pergunta original. (Isto é, matar o buffer sem salvá-lo via C-x # deve disparar o mesmo erro que sai do emacsclient.)

No entanto, minhas tentativas de adicionar isso ao kill-buffer-hook falharam, porque a função server-kill-buffer é colocada na frente da lista kill-buffer-hook depois que os ganchos server-visit-hook foram executados e, portanto, a% padrão A funçãoserver-kill-buffer será executada primeiro. (Pode-se consertar o kill-buffer-hook depois, mas ainda não estou certo de onde colocar o código para fazer isso no fluxo de controle Elisp.)

Atualização: Ok, aqui está uma maneira realmente hacky de realizar o acima:

(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)

Atualização 2: variante ligeiramente mais robusta:

(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)
    
por 28.01.2013 / 16:04
1

Apenas pressione Ctrl+C no terminal onde você está correndo. Isso cancela a edição e empurra a linha original para o histórico. Se você não puder fazer isso diretamente porque o Emacs está rodando no mesmo terminal, mate o processo emacsclient pelos meios de sua escolha.

    
por 11.06.2011 / 01:39