Prima di tutto, un disclaimer. L'ho cercato molte volte e sono abbastanza sicuro di aver già trovato la risposta in un modo o nell'altro, ma non capisco.
Il mio problema è il seguente:
- Ho un processo che passa attraverso Comint
- Voglio inviare una riga di input, acquisire l'output e vedere quando è finita (quando l'ultima riga dell'output corrisponde al regexp per un prompt)
- solo quando il processo ha terminato l'invio dell'output, voglio inviare un'altra riga di input (ad esempio).
Per un po 'di background, pensa a una modalità principale che implementa l'interazione con un programma, che può restituire una quantità arbitraria di output, in un tempo arbitrariamente lungo. Questa non dovrebbe essere una situazione insolita, giusto? Va bene, forse la parte in cui devo attendere tra gli input è insolita, ma presenta alcuni vantaggi rispetto all'invio dell'input nel suo insieme:
- il buffer di output è ben formattato: input output input output ...
- ancora più importante, quando si invia molto testo a un processo, il testo viene tagliato in pezzi e i pezzi vengono incollati indietro dal processo; i punti di taglio sono arbitrari e questo a volte rende l'input non valido (il mio processo non incollerà correttamente un taglio di input nel mezzo di un identificatore, per esempio)
Comunque, insolito o no, si scopre che è complicato. In questo momento, sto usando qualcosa sulla falsariga di
(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 lo chiamo ogni volta dopo aver inviato una linea di input e prima di inviare quella successiva. Bene ... funziona, è già qualcosa.
Ma fa anche emacs in attesa durante l'output. Il motivo è ovvio, e ho pensato che se avessi incluso un tipo di asincrono sleep-for
(per esempio 1s) nel loop, questo avrebbe ritardato l'output di 1s, ma avrebbe soppresso il blocco. Solo che sembra che questo tipo di asincrono
sleep-for
non esista .
O lo fa? Più in generale, esiste un modo idiomatico per raggiungere questo obiettivo con Emacs? In altre parole:
Come inviare input a un processo, attendere l'output, quindi inviare più input, in modo asincrono?
Durante la ricerca (vedi le domande correlate), ho visto principalmente citazioni di sentinelle (ma non penso che si applichi nel mio caso, poiché il processo non termina) e di alcuni hook comint (ma allora cosa? rendere l'hook buffer locale, trasformare il mio "valutare le linee rimanenti" in una funzione, aggiungere questa funzione all'hook e pulire successivamente l'hook? che suona davvero sporco, vero?).
Mi dispiace se non mi sto chiarendo, o se c'è davvero una risposta ovvia disponibile da qualche parte, sono davvero confuso da tutti gli intricati dell'interazione di processo.
Se necessario, posso fare di tutto questo un esempio funzionante, ma temo che farebbe solo un'altra "domanda di processo specifica con una risposta di processo specifica" come tutte quelle che ho trovato prima e che non mi hanno aiutato.
Alcune domande correlate su SO: