Пользовательские строки формата
Иногда бывает полезно позволить пользователям и программам на Lisp управлять генерацией определённого текста с помощью пользовательских управляющих строк формата. Например, строка формата может управлять отображением имени, фамилии и адреса электронной почты человека. Используя функцию format, описанную в предыдущем разделе, строка формата могла бы выглядеть примерно так: "%s %s <%s>". Однако такой подход быстро становится непрактичным, поскольку бывает неясно, какой спецификатор соответствует той или иной части информации.
В таких случаях удобнее использовать строку формата примерно такого вида: "%f %l <%e>", где каждый спецификатор несёт больше семантической информации и его можно легко переставить относительно других спецификаторов, благодаря чему пользователь может проще настраивать такие строки формата.
Функция format-spec, описанная в этом разделе, выполняет функцию, аналогичную format, за исключением того, что она работает со строками управления форматом, в которых используются произвольные символы спецификаторов.
- Функция: format-spec template spec-alist &optional ignore-missing split
-
Эта функция возвращает строку, сформированную из строки формата template в соответствии с преобразованиями, заданными в spec-alist, которая представляет собой ассоциативный список (см. Ассоциативные списки) вида
(letter . replacement). Каждый спецификатор%letterв template при форматировании результирующей строки заменяется на replacement.Символы строки template, кроме спецификаторов формата, напрямую копируются в выходные данные вместе со своими текстовыми свойствами, если они есть. Текстовые свойства спецификаторов формата копируются в соответствующие замены.
Использование ассоциативного списка для задания преобразований даёт несколько полезных свойств:
- Если spec-alist содержит больше уникальных ключей letter, чем уникальных символов спецификаторов в template, неиспользуемые ключи просто игнорируются.
- Если spec-alist содержит несколько ассоциаций с одинаковым letter, используется та, которая расположена ближе всего к началу списка.
- Если в template один и тот же символ спецификатора встречается несколько раз, одна и та же найденная в spec-alist replacement используется для всех подстановок этого символа.
- Порядок спецификаторов в template не обязан соответствовать порядку ассоциаций в spec-alist.
ЗАМЕНА также может быть функцией без аргументов, возвращающей строку для подстановки. Она будет вызвана только в том случае, если соответствующая БУКВА используется в ШАБЛОНЕ. Это полезно, например, чтобы не запрашивать ввод, если он не требуется.
Необязательный аргумент ignore-missing определяет, как обрабатывать символы спецификаторов в template, которых нет в spec-alist. Если аргумент равен
nilили не указан, функция выдаёт ошибку; если он равенignore, такие спецификаторы формата оставляются в выходных данных без изменений, вместе со своими текстовыми свойствами, если они есть; если он равенdelete, такие спецификаторы формата удаляются из выходных данных; любое другое значение, не равноеnil, обрабатывается так же, какignore, но все вхождения ‘%%’ также остаются в выходных данных без изменений.Если необязательный аргумент split не равен
nil, вместо одной строкиformat-specразделит результат на список строк в местах выполнения подстановок. Например:(format-spec "foo %b bar" '((?b . "zot")) nil t) ⇒ ("foo " "zot" " bar")
Синтаксис спецификаторов формата, принимаемых функцией format-spec, похож, но не идентичен синтаксису, принимаемому функцией format. В обоих случаях спецификатор формата представляет собой последовательность символов, начинающуюся с ‘%’ и заканчивающуюся буквой, например ‘s’.
В отличие от format, которая задаёт определённое значение для фиксированного набора символов спецификаторов, format-spec принимает произвольные символы спецификаторов и обрабатывает их одинаково. Например:
(setq my-site-info
(list (cons ?s system-name)
(cons ?t (symbol-name system-type))
(cons ?c system-configuration)
(cons ?v emacs-version)
(cons ?e invocation-name)
(cons ?p (number-to-string (emacs-pid)))
(cons ?a user-mail-address)
(cons ?n user-full-name)))
(format-spec "%e %v (%c)" my-site-info)
⇒ "emacs 27.1 (x86_64-pc-linux-gnu)"
(format-spec "%n <%a>" my-site-info)
⇒ "Emacs Developers <emacs-devel@gnu.org>"
Спецификатор формата может содержать любое количество следующих флагов сразу после ‘%’, чтобы изменить параметры подстановки.
- ‘0’
-
Этот флаг указывает, что для заполнения до заданной ширины следует использовать символы ‘0’ вместо пробелов.
- ‘-’
-
Этот флаг указывает, что заполнение до заданной ширины следует выполнять справа, а не слева.
- ‘<’
-
Этот флаг указывает, что подстановку следует усечь слева до заданной ширины и точности, если они указаны.
- ‘>’
-
Этот флаг указывает, что подстановку следует усечь справа до заданной ширины и точности, если они указаны.
- ‘^’
-
Этот флаг преобразует подставляемый текст в верхний регистр (см. Изменение регистра в Lisp).
- ‘_ (underscore)’
Этот флаг преобразует подставляемый текст в нижний регистр (см. Изменение регистра в Lisp).
Результат использования противоречивых флагов (например, для верхнего и нижнего регистра одновременно) не определён.
Как и в случае с format, спецификатор формата может содержать ширину — десятичное число, указанное после всех флагов, — и точность: десятичную точку ‘.’ с последующим десятичным числом, указанную после всех флагов и ширины.
Если подстановка содержит меньше символов, чем заданная ширина, она дополняется слева:
(format-spec "%8a is padded on the left with spaces"
'((?a . "alpha")))
⇒ " alpha is padded on the left with spaces"
Если подстановка содержит больше символов, чем заданная точность, она усекается справа:
(format-spec "%.2a is truncated on the right"
'((?a . "alpha")))
⇒ "al is truncated on the right"
Ниже приведён более сложный пример, объединяющий несколько рассмотренных выше возможностей:
(setq my-battery-info
(list (cons ?p "73") ; Percentage
(cons ?L "Battery") ; Status
(cons ?t "2:23") ; Remaining time
(cons ?c "24330") ; Capacity
(cons ?r "10.6"))) ; Rate of discharge
(format-spec "%>^-3L : %3p%% (%05t left)" my-battery-info)
⇒ "BAT : 73% (02:23 left)"
(format-spec "%>^-3L : %3p%% (%05t left)"
(cons (cons ?L "AC")
my-battery-info))
⇒ "AC : 73% (02:23 left)"
Как показывают примеры в этом разделе, format-spec часто используется для выборочного форматирования различных фрагментов информации. Это полезно в программах, позволяющих пользователям настраивать строки формата: пользователь может форматировать только часть предоставляемой программой информации, используя обычный синтаксис и выбирая любой желаемый порядок.
Copyright © 1990-1996, 1998-2026 Free Software Foundation, Inc.
Licensed under the GNU GPL license.
https://www.gnu.org/software/emacs/manual/html_node/elisp/Custom-Format-Strings.html