20.4 Потоки вывода

Поток вывода определяет, что делать с символами, полученными при печати. Большинство функций печати принимают поток вывода в качестве необязательного аргумента. Ниже приведены возможные типы потоков вывода:

buffer

Выводимые символы вставляются в buffer в текущей точке. Точка продвигается по мере вставки символов.

marker

Выводимые символы вставляются в буфер, на который указывает marker, в позиции маркера. Позиция маркера продвигается по мере вставки символов. Значение точки в буфере не влияет на печать, когда поток является маркером, и такой вид печати не сдвигает точку (за исключением случаев, когда маркер указывает на позицию точки или раньше, тогда точка продвигается вместе с окружающим текстом, как обычно).

function

Выводимые символы передаются в function, которая отвечает за их сохранение. Она вызывается с одним символом в качестве аргумента столько раз, сколько символов нужно вывести, и отвечает за сохранение символов в любом месте, которое вы хотите указать.

t

Выводимые символы отображаются в области эха. Если Emacs работает в пакетном режиме (см. Пактовый режим), вывод записывается в дескриптор стандартного вывода.

nil

Указание nil в качестве потока вывода означает использование значения переменной standard-output; это значение является потоком вывода по умолчанию и не должно быть nil.

symbol

Символ в качестве потока вывода эквивалентен определению функции этого символа (если таковое имеется).

Многие допустимые потоки вывода также являются допустимыми потоками ввода. Таким образом, разница между потоками ввода и вывода — это скорее вопрос того, как вы используете объект Lisp, а не разница в типах объектов.

Вот пример буфера, используемого в качестве потока вывода. Точка изначально находится, как показано непосредственно перед символом ‘h’ в ‘the’. В конце точка находится непосредственно перед тем же символом ‘h’.

---------- Buffer: foo ----------
This is t∗he contents of foo.
---------- Buffer: foo ----------

(print "This is the output" (get-buffer "foo"))
     ⇒ "This is the output"

---------- Buffer: foo ----------
This is t
"This is the output"
∗he contents of foo.
---------- Buffer: foo ----------

Теперь мы покажем использование маркера в качестве потока вывода. Изначально маркер находится в буфере foo, между символами ‘t’ и ‘h’ в слове ‘the’. В конце маркер продвинулся над вставленным текстом, оставаясь при этом позиционированным перед тем же символом ‘h’. Обратите внимание, что положение точки, показанное обычным образом, не имеет значения.

---------- Buffer: foo ----------
This is the ∗output
---------- Buffer: foo ----------

(setq m (copy-marker 10))
     ⇒ #<marker at 10 in foo>

(print "More output for foo." m)
     ⇒ "More output for foo."

---------- Buffer: foo ----------
This is t
"More output for foo."
he ∗output
---------- Buffer: foo ----------

m
     ⇒ #<marker at 34 in foo>

Следующий пример показывает вывод в область эха:

(print "Echo Area output" t)
     ⇒ "Echo Area output"
---------- Echo Area ----------
"Echo Area output"
---------- Echo Area ----------

Наконец, мы показываем использование функции в качестве потока вывода. Функция eat-output принимает каждый переданный ей символ и конкатенирует его в начало списка last-output (см. Построение конс-ячеек и списков). В конце список содержит все выведенные символы, но в обратном порядке.

(setq last-output nil)
     ⇒ nil

(defun eat-output (c)
  (setq last-output (cons c last-output)))
     ⇒ eat-output

(print "This is the output" #'eat-output)
     ⇒ "This is the output"

last-output
     ⇒ (10 34 116 117 112 116 117 111 32 101 104
    116 32 115 105 32 115 105 104 84 34 10)

Теперь мы можем восстановить правильный порядок вывода, развернув список:

(concat (nreverse last-output))
     ⇒ "
\"This is the output\"
"

Вызов concat преобразует список в строку, чтобы вы могли более ясно увидеть его содержимое.

Функция: external-debugging-output character

Эта функция может быть полезна в качестве потока вывода при отладке. Она записывает character в поток стандартной ошибки.

Например

(print "This is the output" #'external-debugging-output)
-| This is the output
⇒ "This is the output"