Вызовите 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.
Тайлер