Wywołaj emacsclient z programu wywoływanego przez Emacsa

9

Wystąpił problem z przeglądaniem plików dokumentacji pdf w programie AucTex. Używam pdf-toolsdo przeglądania plików PDF z poziomu Emacsa i ustawiłem emacsclient -njako domyślną przeglądarkę pdf (przez xdg-mime w systemie Debian Linux). Działa to dobrze w większości przypadków, ale psuje (Tex-documentation-texdoc ...)funkcję Auctex ( C-c ?).

Zawęziłem problem do jednego wiersza kodu. Kiedy próbuję przeglądać dokumentację listingspakietu, TeX-documentation-texdoczamienia to w następujący sexp:

(shell-command-to-string "texdoc --view  listings")

texdocz kolei wezwania emacsclientdo otwarcia pliku (na podstawie tego, jak skonfigurowałem swój pulpit za pomocą xdg). Jednak w tym momencie Emacs zawiesza się i muszę wyjść z ( C-g), aby odzyskać kontrolę. Po tym nie jest otwierany żaden nowy plik pdf. To samo dzieje się, jeśli spróbuję wywołać emacsclient bezpośrednio:

(shell-command-to-string "emacsclient -n tmp.pdf")

Oba polecenia pracy w linii poleceń (czyli emacsclient -n tmp.pdfi texdoc --view listings.

Moje pytanie brzmi: w takim przypadku jak wywołać emacsclient z poziomu Emacsa? (i wiem, że mogłem po prostu otworzyć plik pdf find-file; nie jest to opcja, ponieważ muszę wywołać proces zewnętrzny (texdoc), aby znaleźć plik, a następnie ten proces wywołuje emacsclient).

Tyler
źródło
Dlaczego nie po prostu użyć, texdoc -M --list listingsaby znaleźć plik, a następnie użyć find-file?
Quarky
@suvayu Po prostu wygoda. Inną alternatywą jest przełączenie się na terminal w celu wywołania, texdoc --viewa następnie przełączenie z powrotem do Emacsa po otwarciu pliku. Ale myślę, że powinien istnieć sposób na zrobienie tego w jednym kroku od Emacsa?
Tyler
1
Czy można (async-shell-command "emacsclient -n tmp.pdf")rozwiązać problem?
Imię
1
@ Imię ciekawe - (async-shell-command "emacsclient -n tmp.pdf")działa, ale nie (async-shell-command "texdoc --view listings")działa. To przydatna wskazówka.
Tyler
1
Czy C-u C-c ?działa Najpierw wyświetla listę dokumentów związanych z pakietem, a następnie otwiera przeglądarkę za pomocą (call-process "texdoc" nil 0 nil "--just-view" doc).
giordano,

Odpowiedzi:

5

Rozwiązaniem jest uruchomienie texdocw ramach procesu asynchronicznego.

Najlepszym sposobem na zrobienie tego jest prawdopodobnie użycie start-file-processzamiast tego shell-command-to-string(jest to przydatna funkcja do szybkiego i brudnego kodu, gdy bardziej celowe jest napisanie małego skryptu powłoki niż odpowiadający mu kod Elisp, ale z mojego doświadczenia wynika, że ​​lepiej go unikać).

Będzie to jednak wymagało znacznych zmian w otaczającym kodzie, ponieważ start-file-processnie zwraca bezpośrednio wyniku procesu, zamiast tego pozwala wskazać, w którym buforze umieścić dane wyjściowe, a następnie należy użyć set-process-sentinelfunkcji wywołania zwrotnego, która pobiera dane wyjściowe z tego bufora i robi „cokolwiek trzeba z tym zrobić” po zakończeniu polecenia.

Stefan
źródło
W konkretnym przypadku uruchamiania texdocw AUCTeX uważam, że użycie wartownika jest nieco przesadzeniem, ponieważ nie jest to podstawowa funkcja (jak otwarcie przeglądarki dokumentu wyjściowego, w którym to przypadku używamy strażnik).
giordano,
Nie mam pojęcia, dlaczego użyto funkcji „-to-string”, więc nie wiem, co się dzieje z wynikiem działania polecenia. Jeśli to wyjście jest potrzebne (jak sugeruje użycie ...-to-string), wówczas rozwiązanie asynchroniczne będzie wymagało albo filtru procesu, albo czujnika procesu. Jeśli nie, to kod może użyć czegoś takiego (shell-command "texdoc --view listings &").
Stefan
Wyjaśniono to w komentarzach do TeX-documentation-texdoc: ...-to-stringwariant służy do pokazywania użytkownikom możliwych komunikatów o błędach (na przykład, gdy nie znaleziono żadnej dokumentacji). Ponadto texdoc nonexistingpackagezwraca 0, ale wartownika można użyć do parsowania danych wyjściowych.
giordano
Wtedy wartownik wydaje się najlepszą opcją.
Stefan
Nie mogę znaleźć inwokacji, start-file-processktóra faktycznie działa tutaj. (start-file-process "texdoc" "*texdoc*" "texdoc" "--view" "listings")tworzy bufor *texdoc*, do którego wstawia się „Przetwarzanie texdoc zakończone”, a pdf nigdy się nie otwiera. To samo dzieje się, gdy ustawiam przeglądarkę pdf xdg-mime na ewince.
Tyler
1

Jeśli musisz tylko przesłać zapytanie do Emacsa, nie czekając na odpowiedź, możesz uruchomić emacsclientw tle. Pod systemami uniksowymi (Linux, macOS, Cygwin,…):

emacsclient … &

W natywnym systemie Windows:

start emacsclient …
Gilles „SO- przestań być zły”
źródło
Jasne, ale w tym konkretnym przypadku muszę wywołać program (texdoc), który następnie wywołuje (emacsclient). Dodatkowy poziom przekierowania powoduje problemy.
Tyler
@Tyler texdocjest asynchroniczny (tzn. Nie czekasz na zakończenie), prawda? Możesz więc zastosować tę samą zasadę: uruchom texdoc … &jako polecenie powłoki.
Gilles 'SO - przestań być zły'
Próbowaliśmy tego w komentarzach pod moim pytaniem; działa, gdy dzwonisz emacsclientbezpośrednio, ale nie dzwonisz texdoc.
Tyler