После создания синхронного процесса Emacs ожидает завершения этого процесса перед продолжением работы. Примером этого является запуск Dired в GNU или Unix29: он запускает ls в синхронном процессе, а затем слегка изменяет вывод. Поскольку процесс синхронный, весь список каталога поступает в буфер до того, как Emacs попытается что-либо с ним сделать.
Пока Emacs ожидает завершения синхронного подпроцесса, пользователь может прервать выполнение, набрав C-g. Первое нажатие C-g пытается завершить подпроцесс сигналом SIGINT, но ожидает фактического завершения подпроцесса перед выходом. Если за это время пользователь нажмет еще раз C-g, это мгновенно завершит подпроцесс сигналом SIGKILL и немедленно выйдет (кроме MS-DOS, где завершение других процессов не работает). См. Прерывание.
Функции синхронных подпроцессов возвращают индикацию того, как завершился процесс.
Вывод из синхронного подпроцесса обычно декодируется с использованием кодировки, подобно тексту, читаемому из файла. Ввод, отправляемый подпроцессу функцией call-process-region, кодируется с использованием кодировки, подобно тексту, записываемому в файл. См. Системы кодирования.
Эта функция вызывает program и ожидает его завершения.
Рабочий каталог подпроцесса устанавливается в значение default-directory текущего буфера, если оно локально (определяется функцией unhandled-file-name-directory), или в "~" в противном случае. Если вы хотите запустить процесс в удаленном каталоге, используйте process-file.
Стандартный ввод для нового процесса поступает из файла infile, если infile не равен nil, и из нулевого устройства в противном случае. Аргумент destination указывает, куда помещать вывод процесса. Вот возможные варианты:
Вставить вывод в этот буфер перед точкой. Сюда входит как стандартный поток вывода, так и стандартный поток ошибок процесса.
Вставить вывод в буфер с этим именем перед точкой.
tВставить вывод в текущий буфер перед точкой.
nilОтбросить вывод.
Отбросить вывод и сразу вернуть nil, не дожидаясь завершения подпроцесса.
В этом случае процесс не является действительно синхронным, поскольку он может выполняться параллельно с Emacs; но вы можете считать его синхронным в том смысле, что Emacs по сути завершает работу с подпроцессом сразу после возврата этой функции.
MS-DOS не поддерживает асинхронные подпроцессы, поэтому этот параметр там не работает.
(:file file-name)Направить вывод в указанное имя файла, перезаписывая его, если он уже существует.
(real-destination error-destination)Разделить стандартный поток вывода и стандартный поток ошибок; обрабатывать обычный вывод, как указано в real-destination, и направлять вывод ошибок согласно error-destination. Если error-destination равен nil, это означает отбросить вывод ошибок, t означает смешивать его с обычным выводом, а строка указывает имя файла для перенаправления вывода ошибок.
Вы не можете напрямую указать буфер для вывода ошибок; это слишком сложно для реализации. Но вы можете достичь этого результата, направив вывод ошибок во временный файл, а затем вставив его в буфер после завершения подпроцесса.
Если display не равен nil, то call-process перерисовывает буфер по мере вставки вывода. (Однако если выбранная для декодирования вывода система кодирования — undecided, то есть определение кодировки по фактическим данным, то перерисовка иногда не может продолжаться после обнаружения не-ASCII символов. Существуют фундаментальные причины, по которым это сложно исправить; см. Получение вывода от процессов.)
В противном случае функция call-process не выполняет перерисовки, и результаты становятся видимыми на экране только тогда, когда Emacs перерисовывает этот буфер в обычном порядке.
Остальные аргументы, args, являются строками, задающими аргументы командной строки для программы. Каждая строка передается program как отдельный аргумент.
Возвращаемое значение call-process (если вы не указали не ждать) указывает причину завершения процесса. Число означает код завершения подпроцесса; 0 означает успех, а любое другое значение — ошибку. Если процесс был завершен сигналом, call-process возвращает строку, описывающую сигнал. Если вы указали call-process не ждать, он возвращает nil.
В примерах ниже текущим является буфер ‘foo’.
(call-process "pwd" nil t)
⇒ 0
---------- Буфер: foo ----------
/home/lewis/manual
---------- Буфер: foo ----------
(call-process "grep" nil "bar" nil "lewis" "/etc/passwd")
⇒ 0
---------- Буфер: bar ----------
lewis:x:1001:1001:Bil Lewis,,,,:/home/lewis:/bin/bash
---------- Буфер: bar ----------
Вот пример использования call-process, который ранее использовался в определении функции insert-directory:
(call-process insert-directory-program nil t nil switches
(if full-directory-p
(concat (file-name-as-directory file) ".")
file))
Эта функция обрабатывает файлы синхронно в отдельном процессе. Она аналогична call-process, но может вызывать обработчик имен файлов на основе значения переменной default-directory, которая задает текущий рабочий каталог подпроцесса.
Аргументы обрабатываются почти так же, как и для call-process, со следующими отличиями:
Некоторые обработчики имен файлов могут не поддерживать все комбинации и формы аргументов infile, buffer и display. Например, некоторые обработчики имен файлов могут вести себя так, как если бы display был равен nil, независимо от фактически переданного значения. В качестве другого примера, некоторые обработчики имен файлов могут не поддерживать разделение стандартного вывода и вывода ошибок через аргумент buffer.
Если вызывается обработчик имен файлов, он определяет программу для запуска на основе первого аргумента program. Например, предположим, что вызывается обработчик для удаленных файлов. Тогда путь, используемый для поиска программы, может отличаться от exec-path.
Второй аргумент infile может вызывать обработчик имен файлов. Обработчик имен файлов может отличаться от обработчика, выбранного для самой функции process-file. (Например, default-directory может находиться на одном удаленном хосте, а infile — на другом. Или default-directory может быть обычным, тогда как infile находится на удаленном хосте.)
Если buffer является списком вида (real-destination error-destination) и error-destination указывает на файл, то применяются те же замечания, что и для infile.
Остальные аргументы (args) будут переданы процессу без изменений. Emacs не участвует в обработке имен файлов, присутствующих в args. Во избежание путаницы лучше избегать абсолютных имен файлов в args, а указывать все имена файлов относительно default-directory. Функция file-relative-name полезна для создания таких относительных имен файлов. Альтернативно, вы можете использовать file-local-name (см. Создание "волшебных" имен файлов), чтобы получить абсолютное имя файла с точки зрения удаленного хоста.
Эта переменная указывает, изменяет ли вызов process-file удаленные файлы.
По умолчанию эта переменная всегда установлена в t, что означает, что вызов process-file потенциально может изменить любой файл на удаленном хосте. Когда она установлена в nil, обработчик имен файлов может оптимизировать свое поведение в отношении кеширования атрибутов удаленных файлов.
Вы должны изменять эту переменную только с помощью let-привязки; никогда не используйте setq.
Эта пользовательская опция указывает, возвращает ли вызов process-file строку, описывающую сигнал, прервавший удаленный процесс.
Когда процесс возвращает код выхода больше 128, это интерпретируется как сигнал. process-file должен возвращать строку, описывающую этот сигнал.
Поскольку существуют процессы, нарушающие это правило и возвращающие коды выхода больше 128, которые не связаны с сигналом, process-file всегда возвращает код выхода как натуральное число для удаленных процессов. Установка этой пользовательской опции в не-nil заставляет process-file интерпретировать такие коды выхода как сигналы и возвращать соответствующую строку.
Эта функция отправляет текст от start до end как стандартный ввод процессу, выполняющему program. Она удаляет отправленный текст, если delete не равен nil; это полезно, когда destination равен t, чтобы вставить вывод в текущий буфер вместо ввода.
Аргументы destination и display управляют тем, что делать с выводом подпроцесса и обновлять ли дисплей по мере поступления данных. Подробности см. в описании call-process выше. Если destination равно целому числу 0, call-process-region отбрасывает вывод и немедленно возвращает nil, не дожидаясь завершения подпроцесса (это работает только при поддержке асинхронных подпроцессов, т.е. не на MS-DOS).
Остальные аргументы, args, являются строками, задающими аргументы командной строки для программы.
Возвращаемое значение call-process-region аналогично возвращаемому значению call-process: nil, если вы указали вернуться без ожидания; в противном случае число или строка, указывающие, как завершился подпроцесс.
В следующем примере мы используем call-process-region для запуска утилиты cat, при этом стандартным вводом являются первые пять символов в буфере ‘foo’ (слово ‘input’). cat копирует свой стандартный ввод в стандартный вывод. Поскольку аргумент destination равен t, этот вывод вставляется в текущий буфер.
---------- Буфер: foo ---------- input∗ ---------- Буфер: foo ----------
(call-process-region 1 6 "cat" nil t)
⇒ 0
---------- Буфер: foo ----------
inputinput∗
---------- Буфер: foo ----------
Например, команда shell-command-on-region использует call-shell-region аналогичным образом:
(call-shell-region
start end
command ; команда оболочки
nil ; не удалять область
buffer) ; отправить вывод в buffer
Эта функция выполняет команду оболочки command синхронно. Остальные аргументы обрабатываются так же, как в call-process. Старое соглашение о вызове позволяло передавать любое количество дополнительных аргументов после display, которые объединялись с command; это все еще поддерживается, но настоятельно не рекомендуется.
Эта функция подобна call-process-shell-command, но внутренне использует process-file. В зависимости от default-directory, command может выполняться также на удаленных хостах. Старое соглашение о вызове позволяло передавать любое количество дополнительных аргументов после display, которые объединялись с command; это все еще поддерживается, но настоятельно не рекомендуется.
Эта функция отправляет текст от start до end как стандартный ввод вложенной оболочке, выполняющей command. Эта функция аналогична call-process-region, но процессом является оболочка. Аргументы delete, destination и возвращаемое значение аналогичны call-process-region.
Обратите внимание, что эта функция не принимает дополнительные аргументы.
Если command указывает на оболочку (например, через shell-file-name), имейте в виду, что поведение различных оболочек при передаче команд в их стандартный ввод зависит от оболочки и системы, и поэтому непереносимо. Различия особенно заметны, когда область включает более одной строки, то есть при передаче в оболочку команд с встроенными символами новой строки. Поэтому Lisp-программы, использующие этот метод, должны форматировать текст в области по-разному, в соответствии с ожиданиями оболочки.
Эта функция выполняет command (строку) как команду оболочки, а затем возвращает вывод команды в виде строки. Если command фактически содержит более одной команды, поведение зависит от вызываемой оболочки (определяется shell-file-name для локальных команд). В частности, разделитель между командами не может быть символом новой строки в MS-Windows; используйте вместо него ‘&&’.
Эта функция запускает program, ожидает его завершения и возвращает его вывод в виде списка строк. Каждая строка в списке содержит одну строку текста, выведенную программой; символы конца строки удаляются из каждой строки. Аргументы после program, args, являются строками, задающими аргументы командной строки для запуска программы.
Если program завершается с ненулевым кодом выхода, эта функция сигнализирует об ошибке.
Эта функция работает путем вызова call-process, поэтому вывод программы декодируется так же, как и для call-process.
Эта функция аналогична process-lines, но не сигнализирует об ошибке, если program завершается с ненулевым кодом выхода.