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


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.


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 …

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.