Primeiro de tudo, um aviso. Pesquisei isso muitas vezes e tenho certeza de que já encontrei a resposta de uma maneira ou de outra, mas simplesmente não a entendo.
Meu problema é o seguinte:
- Eu tenho um processo executando comint
- Quero enviar uma linha de entrada, capturar saída e ver quando ela termina (quando a última linha da saída corresponde ao regexp para um prompt)
- somente quando o processo terminar de enviar a saída, desejo enviar outra linha de entrada (por exemplo).
Para um pouco de segundo plano, pense em um modo principal implementando a interação com um programa, que pode retornar uma quantidade arbitrária de saída, em um tempo arbitrariamente longo. Esta não deve ser uma situação incomum, certo? Ok, talvez a parte em que eu preciso esperar entre as entradas seja incomum, mas ela tenha algumas vantagens sobre o envio da entrada como um todo:
- o buffer de saída está bem formatado: output input input output ...
- mais importante, ao enviar muito texto para um processo, o texto é cortado em pedaços e os pedaços são colados de volta pelo processo; os pontos de corte são arbitrários e isso às vezes gera uma entrada inválida (meu processo não colará corretamente uma entrada no meio de um identificador, por exemplo)
De qualquer forma, incomum ou não, verifica-se que é complicado. No momento, estou usando algo ao longo das linhas de
(defun mymode--wait-for-output ()
(let ((buffer (mymode-get-buffer)))
(with-current-buffer buffer
(goto-char (point-max))
(forward-line 0)
(while (not (mymode-looking-at-prompt))
(accept-process-output nil 0.001)
(redisplay)
(goto-char (point-max))
(forward-line 0))
(end-of-line))))
e eu ligo para isso toda vez depois de enviar uma linha de entrada e antes de enviar a próxima. Bem ... funciona, isso já é alguma coisa.
Mas também faz o emacs travar enquanto aguarda a saída. O motivo é óbvio e achei que, se eu incluísse algum tipo de assíncrono sleep-for
(por exemplo, 1s) no loop, isso atrasaria a saída em 1s, mas suprimiria a interrupção. Exceto que parece que esse tipo de assíncrono
sleep-for
não existe .
Ou faz? De maneira mais geral, existe uma maneira idiomática de conseguir isso com o emacs? Em outras palavras:
Como enviar entrada para um processo, aguardar a saída e enviar mais entradas de forma assíncrona?
Ao pesquisar ao redor (consulte as perguntas relacionadas), vi principalmente menções de sentinelas (mas não acho que isso se aplique no meu caso, já que o processo não termina) e de alguns ganchos comuns (mas então? torne o local do buffer do gancho, transforme em "avaliar as linhas restantes" em uma função, adicione essa função ao gancho e limpe o gancho depois - isso soa muito sujo, não é?).
Sinto muito se não estou me esclarecendo, ou se há realmente uma resposta óbvia disponível em algum lugar, estou realmente confuso com todas as complexidades da interação do processo.
Se necessário, posso fazer disso tudo um exemplo de trabalho, mas tenho medo de que isso faça apenas mais uma "pergunta de processo específica com resposta de processo específica", como todas as que encontrei anteriormente e não me ajudaram.
Algumas perguntas relacionadas ao SO: