Przede wszystkim wyłączenie odpowiedzialności. Badałem to wiele razy i jestem całkiem pewien, że już znalazłem odpowiedź w ten czy inny sposób, ale po prostu jej nie rozumiem.
Mój problem jest następujący:
- Mam proces przebiegający przez komendę
- Chcę wysłać wiersz danych wejściowych, przechwycić dane wyjściowe i zobaczyć, kiedy się skończy (kiedy ostatni wiersz danych wyjściowych pasuje do wyrażenia regularnego w odpowiedzi na monit)
- dopiero gdy proces zakończy wysyłanie danych wyjściowych, chcę wysłać kolejną linię danych wejściowych (na przykład).
Dla odrobiny tła, pomyśl o głównym trybie implementującym interakcję z programem, który może zwrócić dowolną ilość danych wyjściowych w dowolnie długim czasie. To nie powinna być niezwykła sytuacja, prawda? Okej, może ta część, w której muszę czekać między danymi wejściowymi, jest niezwykła, ale ma kilka zalet w porównaniu z wysyłaniem danych wejściowych jako całości:
- bufor wyjściowy jest ładnie sformatowany: dane wejściowe dane wyjściowe dane wyjściowe ...
- co ważniejsze, podczas wysyłania dużej ilości tekstu do procesu, tekst jest cięty na kawałki i kawałki są wklejane z powrotem przez proces; punkty cięcia są dowolne, co czasami powoduje nieprawidłowe wprowadzanie danych (na przykład mój proces nie wkleja poprawnie wycięcia wejściowego w środku identyfikatora)
W każdym razie, niezwykłe czy nie, okazuje się, że jest skomplikowane. W tej chwili używam czegoś w stylu
(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))))
i wywołuję to za każdym razem po wysłaniu linii wejściowej, a przed wysłaniem następnej. Cóż ... to działa, to już coś.
Ale powoduje również zawieszenie się emacsa podczas oczekiwania na wynik. Powód jest oczywisty i doszedłem do wniosku, że jeśli włączyłem jakiś rodzaj asynchroniczny sleep-for
(na przykład 1s) do pętli, opóźniłoby to wyjście o 1s, ale tłumiłoby zawieszanie. Tyle że wydaje się, że tego rodzaju asynchroniczny
sleep-for
nie istnieje .
A może to? Mówiąc bardziej ogólnie, czy istnieje idiomatyczny sposób na osiągnięcie tego za pomocą emacsa? Innymi słowy:
Jak wysłać dane wejściowe do procesu, poczekać na dane wyjściowe, a następnie wysłać asynchronicznie więcej danych wejściowych?
Podczas przeszukiwania (patrz powiązane pytania) widziałem głównie wzmianki o wartownikach (ale nie sądzę, żeby miało to zastosowanie w moim przypadku, ponieważ proces się nie kończy) i niektórych haczyków (ale co z tego? ustaw bufor bufora na lokalny, zamień moją „ocenę pozostałych linii” na funkcję, dodaj tę funkcję do haka i wyczyść hak później? to brzmi naprawdę brudno, prawda?).
Przykro mi, jeśli nie wyrażam się jasno lub jeśli gdzieś istnieje naprawdę oczywista odpowiedź, jestem naprawdę zdezorientowany wszystkimi zawiłościami interakcji procesu.
W razie potrzeby mogę uczynić z tego cały działający przykład, ale obawiam się, że stworzy to jeszcze jedno „konkretne pytanie procesowe z konkretną odpowiedzią procesową”, jak wszystkie te, które znalazłem wcześniej i nie pomogło mi.
Niektóre powiązane pytania dotyczące SO: