Вызовите emacsclient из программы, вызываемой Emacs


9

Я столкнулся с проблемой просмотра PDF-файлов документации с AucTex. Я использую pdf-toolsдля просмотра PDF-файлов из Emacs, и я установил emacsclient -npdf-viewer по умолчанию (через xdg-mime в Debian Linux). В большинстве случаев это работает нормально, но нарушает (Tex-documentation-texdoc ...)функцию Auctex ( C-c ?).

Я сузил проблему до одной строки кода. Когда я пытаюсь просмотреть документацию для listingsпакета, TeX-documentation-texdocпревращает это в следующий sexp:

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

texdocв свою очередь призывает emacsclientфактически открыть файл (в зависимости от того, как я настроил свой рабочий стол через xdg). Однако на этом этапе Emacs зависает, и мне нужно выйти ( C-g), чтобы вернуть контроль. После этого новый PDF не открывается. То же самое происходит, если я пытаюсь вызвать emacsclient напрямую:

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

Обе команды работают в командной строке (то есть, emacsclient -n tmp.pdfи texdoc --view listings.

Мой вопрос, как в таком случае, как я могу вызвать emacsclient из Emacs? (и я знаю, что могу просто открыть файл pdf с помощью find-file; здесь это не вариант, так как мне нужно вызвать внешний процесс (texdoc), чтобы найти файл, и этот процесс затем вызывает emacsclient).


Почему бы просто не использовать, texdoc -M --list listingsчтобы найти файл, а затем использовать find-file?
— Quarky 22.12.16

@suvayu Просто удобство. Другой альтернативой является переключение на терминал для вызова, texdoc --viewа затем переключение обратно на Emacs, когда он открывает файл. Но я думаю, что должен быть способ сделать это за один шаг от Emacs?
— Тайлер

1
Может (async-shell-command "emacsclient -n tmp.pdf")решить проблему?
— Имя

1
@ Имя интересное - (async-shell-command "emacsclient -n tmp.pdf")работает, а не (async-shell-command "texdoc --view listings")нет. Так что это полезная подсказка.
— Тайлер

1
Работает ли C-u C-c ?? Сначала отображается список документов, связанных с пакетом, а затем открывается окно просмотра (call-process "texdoc" nil 0 nil "--just-view" doc).
— Джордано

Ответы:


5

Решение состоит в том, чтобы работать texdocв асинхронном процессе.

Лучший способ сделать это, вероятно, использовать start-file-processвместо shell-command-to-string(что является удобной функцией для быстрого и грязного кода, когда более целесообразно написать небольшой сценарий оболочки, чем соответствующий код Elisp, но в моем случае лучше избегать этого).

Но это потребует существенных изменений в окружающем коде, так start-file-processкак не возвращает вывод процесса напрямую, вместо этого он позволяет указать, в какой буфер помещать вывод, а затем вам нужно использовать set-process-sentinelфункцию обратного вызова, которая извлекает вывод из этого буфера и делает "все, что нужно сделать с ним", когда команда заканчивается.


В конкретном случае запуска texdocв AUCTeX я считаю использование дозорного немного излишним, так как это не принципиальная особенность (как, например, открытие программы просмотра для выходного документа, и в этом случае мы используем сторожевой).
— Джордано

Я понятия не имею, почему была использована функция "-to-string", поэтому я не знаю, что делается с выводом команды. Если этот вывод необходим (как предполагает использование ...-to-string), тогда асинхронному решению понадобится либо фильтр процесса, либо процессор процесса. Если нет, то код может использовать что-то вроде (shell-command "texdoc --view listings &").
— Стефан

Это объясняется в комментариях к TeX-documentation-texdoc: ...-to-stringвариант используется, чтобы показать пользователям возможные сообщения об ошибках (например, когда документация не найдена). Кроме того, texdoc nonexistingpackageвозвращает 0, но для анализа вывода может использоваться часовой.
— Джордано

Тогда часовой кажется лучшим вариантом.
— Стефан

Я не могу найти вызов, start-file-processкоторый действительно работает здесь. (start-file-process "texdoc" "*texdoc*" "texdoc" "--view" "listings")создает буфер *texdoc*, в который вставляется «Процесс texdoc закончен», и PDF никогда не открывается. То же самое происходит, когда я устанавливаю средство просмотра PDF-файлов xdg-mime также.
— Тайлер

1

Если вам нужно только отправить запрос в Emacs, не дожидаясь ответа, вы можете работать emacsclientв фоновом режиме. Под операционными системами в стиле Unix (Linux, macOS, Cygwin,…):

emacsclient … &

Под родной виндой:

start emacsclient …

Конечно, но в этом конкретном случае мне нужно вызвать программу (texdoc), которая затем вызывает (emacsclient). Дополнительный уровень перенаправления вызывает проблемы.
— Тайлер

@Tyler texdocасинхронный (то есть вы не ждете его завершения), не так ли? Таким образом, вы можете применить тот же принцип: запустить texdoc … &как команду оболочки.
— Жиль "ТАК - перестань быть злым"

Мы попробовали это в комментариях под моим вопросом; работает при звонке emacsclientнапрямую, но не при звонке texdoc.
— Тайлер
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.