Spec-Zone.ru › Elisp

Пользовательские строки формата

Иногда бывает полезно позволить пользователям и программам на 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

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API