В этом разделе мы описываем, как создать асинхронный процесс. После создания асинхронный процесс выполняется параллельно с Emacs, и Emacs может взаимодействовать с ним с помощью функций, описанных в следующих разделах (см. Отправка ввода в процессы и см. Получение вывода из процессов). Обратите внимание, что связь с процессом является лишь частично асинхронной: Emacs отправляет и получает данные из процесса только тогда, когда вызываются эти функции.
Асинхронный процесс контролируется либо через pty (псевдотерминал), либо через pipe. Выбор pty или pipe осуществляется при создании процесса, по умолчанию на основе значения переменной process-connection-type (см. ниже). Если они доступны, pty обычно предпочтительны для процессов, видимых пользователю, например, в режиме Shell, поскольку они позволяют выполнять управление заданиями (C-c, C-z и т. д.) между процессом и его дочерними процессами, а также потому, что интерактивные программы рассматривают pty как терминальные устройства, тогда как pipe не поддерживает эти функции. Однако для подпроцессов, используемых программами Lisp для внутренних целей (т. е. не требуется взаимодействия с подпроцессом пользователем), где необходимо обменивать значительные объемы данных между подпроцессом и программой Lisp, часто лучше использовать pipe, поскольку pipe более эффективен. Кроме того, общее количество pty ограничено на многих системах, и не следует их неоправданно тратить.
Эта функция является базовым низкоуровневым примитивом для запуска асинхронных подпроцессов. Она возвращает объект процесса, представляющий подпроцесс. По сравнению с более высокоуровневой функцией start-process, описанной ниже, она принимает аргументы в виде ключевых слов, более гибка и позволяет указать фильтры процессов и центрирующие функции в одном вызове.
Аргументы args — это список пар "ключевое слово/значение". Опущение ключевого слова всегда эквивалентно указанию его со значением nil. Вот значимые ключевые слова:
:name nameИспользуйте строку name как имя процесса; если процесс с этим именем уже существует, то name изменяется (добавляется «<1>», и т. д.), чтобы сделать его уникальным.
:buffer bufferИспользуйте buffer как буфер процесса. Если значение равно nil, подпроцесс не связан ни с каким буфером.
:command commandИспользуйте command как командную строку процесса. Значение должно быть списком, начинающимся с имени исполняемого файла программы, за которым следуют строки, передаваемые программе в качестве аргументов. Если первый элемент списка равен nil, Emacs открывает новый псевдотерминал (pty) и связывает его ввод и вывод с buffer, не запуская при этом никакой программы; остальные элементы списка в этом случае игнорируются.
:coding codingЕсли coding является символом, он указывает систему кодирования, которая будет использоваться как для чтения, так и для записи данных из соединения и в него. Если coding является ячейкой конс (decoding . encoding), то decoding будет использоваться для чтения, а encoding — для записи. Система кодирования, используемая для кодирования данных, записываемых в программу, также используется для кодирования аргументов командной строки (но не самой программы, имя файла которой кодируется как любое другое имя файла; см. file-name-coding-system).
Если coding равен nil, применяются правила по умолчанию для поиска системы кодирования. См. Системы кодирования по умолчанию.
:connection-type typeИнициализируйте тип устройства, используемого для связи с подпроцессом. Возможные значения: pty для использования pty, pipe для использования pipe или nil для использования значения по умолчанию, полученного из переменной process-connection-type. Если type является ячейкой конс (input . output), то input будет использоваться для стандартного ввода, а output — для стандартного вывода (и стандартной ошибки, если :stderr равен nil).
В системах, где pty недоступны (MS-Windows), этот параметр игнорируется, и используются pipe без условий.
:noquery query-flagИнициализируйте флаг запроса процесса значением query-flag. См. Запрос перед выходом.
:stop stoppedЕсли указано, stopped должен быть nil; использование любого значения, отличного от nil, является ошибкой. Ключ :stop в противном случае игнорируется и сохраняется для совместимости с другими типами процессов, такими как процессы pipe. Асинхронные подпроцессы никогда не запускаются в остановленном состоянии.
:filter filterИнициализируйте фильтр процесса значением filter. Если не указан, будет предоставлен фильтр по умолчанию, который можно будет изменить позже. См. Функции фильтрации процессов.
:sentinel sentinelИнициализируйте центрирующую функцию процесса значением sentinel. Если не указана, будет использована центрирующая функция по умолчанию, которую можно будет изменить позже. См. Центрирующие функции: обнаружение изменений состояния процесса.
:stderr stderrПривяжите stderr к стандартной ошибке процесса. Значение, отличное от nil, должно быть либо буфером, либо процессом pipe, созданным с помощью make-pipe-process, описанной ниже. Если stderr равен nil, стандартная ошибка смешивается со стандартным выводом, и оба отправляются в buffer или filter.
Если stderr — это буфер, Emacs создаст процесс pipe, процесс стандартной ошибки. Этот процесс будет иметь фильтр по умолчанию (см. Функции фильтрации процессов), центрирующую функцию (см. Центрирующие функции: обнаружение изменений состояния процесса) и системы кодирования (см. Системы кодирования по умолчанию). С другой стороны, он будет использовать query-flag в качестве флага запроса при выходе (см. Запрос перед выходом). Он будет связан с буфером stderr (см. Буферы процессов) и отправлять свой вывод (который является стандартной ошибкой основного процесса) туда. Чтобы получить объект процесса для процесса стандартной ошибки, передайте буфер stderr в get-buffer-process.
Если stderr — это процесс pipe, Emacs использует его как процесс стандартной ошибки для нового процесса.
:file-handler file-handlerЕсли file-handler не равен nil, то ищите обработчик имен файлов для default-directory текущего буфера и вызывайте этот обработчик имен файлов для создания процесса. Если такого обработчика нет, продолжайте, как если бы file-handler был nil.
Исходный список аргументов, измененный фактической информацией о соединении, доступен через функцию process-contact.
Текущая рабочая директория подпроцесса устанавливается в значение default-directory текущего буфера, если оно локально (определяется unhandled-file-name-directory), или в ~ в противном случае. Если вы хотите запустить процесс в удаленном каталоге, передайте :file-handler t в make-process. В этом случае текущая рабочая директория — это локальная составляющая default-directory (определяется file-local-name).
В зависимости от реализации обработчика имен файлов, может быть невозможно применить filter или sentinel к полученному объекту процесса. Аргумент :stderr не может быть процессом pipe, обработчики имен файлов не поддерживают процессы pipe для этого. Буфер в качестве аргумента :stderr принимается, его содержимое отображается без использования процессов pipe. См. Функции фильтрации процессов, Центрирующие функции: обнаружение изменений состояния процесса и Прием вывода из процессов.
Некоторые обработчики имен файлов могут не поддерживать make-process. В таких случаях эта функция ничего не делает и возвращает nil.
Эта функция создает двунаправленный pipe, который может быть присоединен к дочернему процессу. Это полезно с ключевым словом :stderr функции make-process. Функция возвращает объект процесса.
Аргументы args — это список пар "ключевое слово/значение". Опущение ключевого слова всегда эквивалентно указанию его со значением nil.
Вот значимые ключевые слова:
:name nameИспользуйте строку name как имя процесса. Как и в make-process, оно изменяется при необходимости, чтобы сделать его уникальным.
:buffer bufferИспользуйте buffer как буфер процесса.
:coding codingЕсли coding является символом, он указывает систему кодирования, которая будет использоваться как для чтения, так и для записи данных из соединения и в него. Если coding является ячейкой конс (decoding . encoding), то decoding будет использоваться для чтения, а encoding — для записи.
Если coding равен nil, применяются правила по умолчанию для поиска системы кодирования. См. Системы кодирования по умолчанию.
:noquery query-flagИнициализируйте флаг запроса процесса значением query-flag. См. Запрос перед выходом.
:stop stoppedЕсли stopped не равен nil, запустите процесс в остановленном состоянии. В остановленном состоянии процесс pipe не принимает входящие данные, но вы можете отправлять исходящие данные. Остановленное состояние устанавливается функцией stop-process и сбрасывается функцией continue-process (см. Отправка сигналов процессам).
:filter filterИнициализируйте фильтр процесса значением filter. Если не указан, будет предоставлен фильтр по умолчанию, который можно будет изменить позже. См. Функции фильтрации процессов.
:sentinel sentinelИнициализируйте центрирующую функцию процесса значением sentinel. Если не указана, будет использована центрирующая функция по умолчанию, которую можно будет изменить позже. См. Центрирующие функции: обнаружение изменений состояния процесса.
Исходный список аргументов, измененный фактической информацией о соединении, доступен через функцию process-contact.
Эта функция является более высокоуровневой оберткой вокруг make-process, предоставляющей интерфейс, похожий на call-process. Она создает новый асинхронный подпроцесс и запускает указанную program в нем. Она возвращает объект процесса, который представляет новый подпроцесс в Lisp. Аргумент name указывает имя для объекта процесса; как и в make-process, оно изменяется при необходимости, чтобы сделать его уникальным. Буфер buffer-or-name — это буфер, который связывается с процессом.
Если program равен nil, Emacs открывает новый псевдотерминал (pty) и связывает его ввод и вывод с buffer-or-name, не создавая подпроцесс. В этом случае оставшиеся аргументы args игнорируются.
Остальные аргументы args — это строки, которые указывают аргументы командной строки для подпроцесса.
В приведенном ниже примере первый процесс запускается и выполняется (а точнее, спит) в течение 100 секунд (буфер вывода «foo» создается немедленно). Тем временем запускается второй процесс, и ему присваивается имя «my-process<1>» для обеспечения уникальности. Он вставляет список каталогов в конец буфера «foo» до завершения первого процесса. Затем он завершается, и в буфер вставляется сообщение об этом. Гораздо позже завершается первый процесс, и для него в буфер вставляется еще одно сообщение.
(start-process "my-process" "foo" "sleep" "100")
⇒ #<process my-process>
(start-process "my-process" "foo" "ls" "-l" "/bin")
⇒ #<process my-process<1>>
---------- Buffer: foo ----------
total 8336
-rwxr-xr-x 1 root root 971384 Mar 30 10:14 bash
-rwxr-xr-x 1 root root 146920 Jul 5 2011 bsd-csh
…
-rwxr-xr-x 1 root root 696880 Feb 28 15:55 zsh4
Process my-process<1> finished
Process my-process finished
---------- Buffer: foo ----------
Как и start-process, эта функция запускает новый асинхронный подпроцесс, в котором выполняется program, и возвращает его объект процесса.
Разница с start-process в том, что эта функция может вызывать обработчик имен файлов на основе значения default-directory. Этот обработчик должен запустить program, возможно, на локальном хосте, возможно, на удаленном хосте, соответствующем default-directory. В последнем случае локальная часть default-directory становится рабочей директорией процесса.
Эта функция не пытается вызывать обработчики имен файлов для program или для остальной части args. По этой причине, если program или любой из args используют синтаксис удаленного файла (см. Обеспечение «магических» имен файлов), их необходимо преобразовать либо в имена файлов относительно default-directory, либо в имена, идентифицирующие файлы локально на удаленном хосте, запустив их через file-local-name.
В зависимости от реализации обработчика имен файлов, может быть невозможно применить process-filter или process-sentinel к полученному объекту процесса. См. Функции фильтрации процессов и Центрирующие функции: обнаружение изменений состояния процесса.
Некоторые обработчики имен файлов могут не поддерживать start-file-process (например, функция ange-ftp-hook-function). В таких случаях эта функция ничего не делает и возвращает nil.
Эта функция похожа на start-process, за исключением того, что она использует оболочку для выполнения указанной command. Аргумент command — это строка команды оболочки. Переменная shell-file-name указывает, какую оболочку использовать.
Цель запуска программы через оболочку, а не напрямую с помощью make-process или start-process, заключается в том, чтобы вы могли использовать функции оболочки, такие как подстановочные знаки в аргументах. Следовательно, если вы включаете любые произвольные аргументы, указанные пользователем, в команду, вы должны сначала заключить их в кавычки с помощью shell-quote-argument, чтобы любые специальные символы оболочки не имели своих специальных значений в оболочке. См. Аргументы оболочки. Конечно, при выполнении команд на основе ввода пользователя следует также учитывать последствия безопасности.
Эта функция похожа на start-process-shell-command, но использует start-file-process внутренне. Благодаря этому command также может быть выполнен на удаленных хостах, в зависимости от default-directory.
Эта переменная контролирует тип устройства, используемого для связи с асинхронными подпроцессами. Если она не равна nil, используются pty, если они доступны. В противном случае используются pipe.
Значение process-connection-type вступает в силу при вызове make-process или start-process. Таким образом, вы можете указать, как общаться с одним подпроцессом, привязывая переменную вокруг вызова этих функций.
Обратите внимание, что значение этой переменной игнорируется, когда make-process вызывается с не-nil значением параметра :stderr; в этом случае Emacs будет общаться с процессом с помощью pipe. Оно также игнорируется, если pty недоступны (MS-Windows).
(let ((process-connection-type nil)) ; использовать pipe
(start-process …))
Чтобы определить, получил ли данный подпроцесс на самом деле pipe или pty, используйте функцию process-tty-name (см. Информация о процессе).
Если функция центрирующей функции/фильтра процесса выдает ошибку, Emacs (по умолчанию) приостанавливает Emacs на process-error-pause-time секунд после отображения этой ошибки, чтобы пользователи увидели соответствующую ошибку. Однако это может привести к ситуациям, когда Emacs становится неотзывчивым (если происходит много таких ошибок), поэтому это можно отключить, установив process-error-pause-time в 0.