Формат модуля
module Format: sig .. end
Красивый вывод.
Если вы новичок в этом модуле, ознакомьтесь с примерами ниже.
Этот модуль реализует механизм красивого вывода для форматирования значений в 'блоках красивого вывода' и 'семантических тегах' в сочетании с набором функций, подобных printf. Форматировщик разбивает строки по указанным разрывам и отступает строки в соответствии со структурой блока. Аналогично, семантические теги могут использоваться для отделения представления текста от его содержимого.
Этот механизм красивого вывода реализован как наложение поверх абстрактных форматировщиков, которые предоставляют базовые функции вывода. Некоторые форматировщики определены предварительно, в частности:
-
Format.std_formatterвыводит в stdout -
Format.err_formatterвыводит в stderr
Большинство функций в модуле Format представлены в двух вариантах: короткая версия, которая работает с стандартным форматировщиком текущего домена, полученного с помощью Format.get_std_formatter, и общая версия, которая начинается с префикса pp_ и принимает форматировщик в качестве первого аргумента. Для версии, работающей со стандартным форматировщиком текущего домена, вызов Format.get_std_formatter откладывается до получения последнего аргумента.
Дополнительные форматировщики можно создать с помощью Format.formatter_of_out_channel, Format.formatter_of_buffer, Format.formatter_of_symbolic_output_buffer или используя пользовательские форматировщики.
Предупреждение: Поскольку форматировщики содержат изменяемое состояние, использование одного и того же форматировщика в нескольких доменах параллельно без синхронизации небезопасно.
Если несколько доменов записывают в один и тот же канал вывода, используя предопределенные форматировщики (полученные с помощью Format.get_std_formatter или Format.get_err_formatter), вывод из доменов будет чередоваться в точках сброса форматировщиков, таких как Format.print_flush. Эта синхронизация не выполняется для форматировщиков, полученных из Format.formatter_of_out_channel (для стандартных каналов вывода или других).
Введение
Вы можете рассматривать этот модуль как расширение для printf механизма для обеспечения автоматического разбиения строк. Добавление аннотаций красивого вывода к вашим обычным printf строкам форматирования предоставляет вам красивые отступы и переносы строк. Аннотации красивого вывода описаны ниже в документации функции Format.fprintf.
Вы также можете использовать явное управление блоками красивого вывода и функции печати, предоставляемые этим модулем. Этот стиль более базовый, но более подробный, чем лаконичные fprintf строки форматирования.
Например, последовательность open_box 0; print_string "x ="; print_space ();, которая печатает
print_int 1; close_box (); print_newline ()x = 1 внутри блока красивого вывода, может быть сокращена как printf "@[%s@ %i@]@." "x =" 1, или даже короче printf "@[x =@ %i@]@." 1.
Правило большого пальца для случайных пользователей этой библиотеки:
- использовать простые блоки красивого вывода (полученные с помощью
open_box 0); - использовать простые разрывы, полученные с помощью
print_cut (), который выводит простой разрыв, или с помощьюprint_space (), который выводит пробел, обозначающий разрыв; - после открытия блока красивого вывода выводите его содержимое с помощью базовых функций печати (например,
print_intиprint_string); - после вывода содержимого блока красивого вывода, закройте блок с помощью
close_box (); - в конце красивого вывода сбросьте форматировщик, чтобы отобразить всё оставшееся содержимое, например, вычислите
print_newline ().
Поведение команд красивого вывода неопределено, если нет открытого блока красивого вывода. Каждый блок, открытый одной из функций open_ ниже, должен быть закрыт с помощью close_box для правильного форматирования. В противном случае часть содержимого, напечатанного в блоках, может не быть выведена или может быть отформатирована неправильно.
В случае интерактивного использования каждая фраза выполняется в начальном состоянии стандартного форматировщика: после выполнения каждой фразы интерактивная система закрывает все открытые блоки красивого вывода, сбрасывает все ожидающие тексты и сбрасывает стандартный форматировщик.
Предупреждение: смешивание вызовов функций красивого вывода этого модуля с вызовами функций вывода Stdlib низкого уровня чревато ошибками.
Функции красивого вывода выдают содержимое, отложенное в очереди форматировщика и стеках, чтобы вычислить правильное разбиение строк. В отличие от этого, базовые функции ввода-вывода записывают напрямую в устройство вывода. Вследствие этого, вывод базовой функции ввода-вывода может появиться до вывода функции красивого вывода, которая была вызвана ранее. Например, приводит к выводу
Stdlib.print_string "<";
Format.print_string "PRETTY";
Stdlib.print_string ">";
Format.print_string "TEXT";
<>PRETTYTEXT.
Форматировщики
type formatter
Абстрактные данные, соответствующие форматировщику (также называемому форматом) и всем его механизмам. Смотрите также Определение форматов.
Блоки красивого вывода
Двигатель красивого вывода использует понятия блока красивого вывода и подсказки разрыва для управления отступами и разбиением строк форматировщиком.
Каждый тип блока красивого вывода вводит специфическую политику разбиения строк:
- внутри горизонтального блока, подсказки разрыва никогда не разбивают строку (но строка может быть разделена в блоке, вложенном глубже),
- внутри вертикального блока, подсказки разрыва всегда разбивают строку,
- внутри горизонтально/вертикального блока, если блок помещается в текущей строке, то подсказки разрыва никогда не разбивают строку, в противном случае подсказка разрыва всегда разбивает строку,
- внутри сжимающегося блока, подсказка разрыва никогда не разбивает строку, если только нет больше места в текущей строке.
Обратите внимание, что политика разбиения строк относится к конкретному блоку: политика блока не управляет политикой внутренних блоков. Например, если вертикальный блок вложен в горизонтальный блок, все подсказки разрыва внутри вертикального блока будут разбивать строку.
Кроме того, открытие блока после предельного значения отступа разбивает строку, независимо от того, поместится ли блок в строке или нет.
val pp_open_box : formatter -> int -> unit
val open_box : int -> unit
pp_open_box ppf d открывает новый сжимающийся блок красивого вывода со смещением d в форматировщике ppf.
Внутри этого блока форматировщик печатает как можно больше материала на каждой строке.
Подсказка разрыва разбивает строку, если больше нет места в строке для печати остатка блока.
Внутри этого блока форматировщик подчёркивает структуру блока: если структурный блок не помещается полностью на простую строку, подсказка разрыва также разбивает строку, если разделение «смещается влево» (то есть новая строка получает отступ меньше, чем текущая строка).
Этот блок — это блок красивого вывода общего назначения.
Если форматировщик разбивает строку в блоке, к текущему отступу добавляется смещение d.
val pp_close_box : formatter -> unit -> unit
val close_box : unit -> unit
Закрывает последний открытый блок красивого вывода.
val pp_open_hbox : formatter -> unit -> unit
val open_hbox : unit -> unit
pp_open_hbox ppf () открывает новый 'горизонтальный' блок красивого вывода.
Этот блок печатает материал на одной строке.
Подсказки разрыва в горизонтальном блоке никогда не разбивают строку. (Разбиение строки всё ещё может произойти внутри вложенных блоков).
val pp_open_vbox : formatter -> int -> unit
val open_vbox : int -> unit
pp_open_vbox ppf d открывает новый 'вертикальный' блок красивого вывода со смещением d.
Этот блок печатает материал на столько строк, сколько подсказок разрыва в блоке.
Каждая подсказка разрыва в вертикальном блоке разбивает строку.
Если форматировщик разбивает строку в блоке, к текущему отступу добавляется d.
val pp_open_hvbox : formatter -> int -> unit
val open_hvbox : int -> unit
pp_open_hvbox ppf d открывает новый 'горизонтально/вертикальный' блок красивого вывода со смещением d.
Этот блок ведёт себя как горизонтальный блок, если он помещается на одной строке, в противном случае он ведёт себя как вертикальный блок.
Если форматировщик разбивает строку в блоке, к текущему отступу добавляется d.
val pp_open_hovbox : formatter -> int -> unit
val open_hovbox : int -> unit
pp_open_hovbox ppf d открывает новый 'горизонтально-или-вертикальный' блок красивого вывода со смещением d.
Этот блок печатает материал как можно больше на каждой строке.
Подсказка разрыва разбивает строку, если больше нет места в строке для печати остатка блока.
Если форматировщик разбивает строку в блоке, к текущему отступу добавляется d.
Функции форматирования
val pp_print_string : formatter -> string -> unit
val print_string : string -> unit
pp_print_string ppf s печатает s в текущем блоке красивого вывода.
val pp_print_bytes : formatter -> bytes -> unit
val print_bytes : bytes -> unit
pp_print_bytes ppf b печатает b в текущем блоке красивого вывода.
- Since 4.13
val pp_print_as : formatter -> int -> string -> unit
val print_as : int -> string -> unit
pp_print_as ppf len s печатает s в текущем блоке красивого вывода. Форматировщик форматирует s так, как будто его длина равна len.
val pp_print_int : formatter -> int -> unit
val print_int : int -> unit
Выводит целое число в текущем блоке красивого вывода.
val pp_print_float : formatter -> float -> unit
val print_float : float -> unit
Выводит число с плавающей точкой в текущем блоке красивого вывода.
val pp_print_char : formatter -> char -> unit
val print_char : char -> unit
Выводит символ в текущем блоке красивого вывода.
val pp_print_bool : formatter -> bool -> unit
val print_bool : bool -> unit
Выводит булево значение в текущем блоке красивого вывода.
val pp_print_nothing : formatter -> unit -> unit
Ничего не выводить.
- Since 5.2
Подсказки для переноса строк
«Подсказка для переноса строки» сообщает красивому принтеру, что нужно вывести пробел или разбить строку тем способом, который лучше подходит к текущим правилам разбиения строк красивого принтера.
Подсказки для переноса строк используются для разделения элементов вывода и являются обязательными для правильного разбиения строк и отступа элементов красивым принтером.
Простые подсказки для переноса строк:
- «пробел»: вывести пробел или разбить строку, если это уместно,
- «разрыв»: разбить строку, если это уместно.
Примечание: понятия пробела и разбиения строк абстрактны для движка красивого принтера, поскольку эти понятия могут быть полностью переопределены программистом. Однако в стандартных настройках красивого принтера «вывести пробел» означает просто вывод символа пробела (ASCII-код 32), а «разбить строку» означает вывод символа новой строки (ASCII-код 10).
val pp_print_space : formatter -> unit -> unit
val print_space : unit -> unit
pp_print_space ppf () выводит подсказку для переноса строки «пробел»: красивый принтер может разбить строку в этой точке, в противном случае выводится один пробел.
pp_print_space ppf () эквивалентно pp_print_break ppf 1 0.
val pp_print_cut : formatter -> unit -> unit
val print_cut : unit -> unit
pp_print_cut ppf () выводит подсказку для переноса строки «разрыв»: красивый принтер может разбить строку в этой точке, в противном случае ничего не выводится.
pp_print_cut ppf () эквивалентно pp_print_break ppf 0 0.
val pp_print_break : formatter -> int -> int -> unit
val print_break : int -> int -> unit
pp_print_break ppf nspaces offset выводит подсказку для переноса строки «полный разрыв»: красивый принтер может разбить строку в этой точке, в противном случае выводится nspaces пробелов.
Если красивый принтер разбивает строку, к текущему отступу добавляется offset.
val pp_print_custom_break : formatter -> fits:string * int * string -> breaks:string * int * string -> unit
pp_print_custom_break ppf ~fits:(s1, n, s2) ~breaks:(s3, m, s4) выводит пользовательскую подсказку для переноса строки: красивый принтер может разбить строку в этой точке.
Если он не разбивает строку, то выводится s1, затем n пробела, затем s2.
Если он разбивает строку, то выводится строка s3, затем отступ (согласно правилам блока), затем смещение на m пробелов, затем строка s4.
В то время как n и m обрабатываются formatter_out_functions.out_indent, сами строки будут обрабатываться formatter_out_functions.out_string. Это позволяет использовать настраиваемый форматировщик, который обрабатывает отступы отдельно, например, выводит теги <br/> или сущности .
Пользовательская подсказка для переноса строки полезна, если вы хотите изменить отображаемые (не содержащие пробелы) символы, которые выводятся в случае разбиения строки или сохранения строки. Например, при выводе списка [a; b; c] , возможно, вы захотите добавить заключительный символ «;», если он выводится вертикально:
[ a; b; c; ]
Вы можете сделать это следующим образом:
printf "@[<v 0>[@;<0 2>@[<v 0>a;@,b;@,c@]%t]@]@\n"
(pp_print_custom_break ~fits:("", 0, "") ~breaks:(";", 0, ""))
- Since 4.08
val pp_force_newline : formatter -> unit -> unit
val force_newline : unit -> unit
Принудительно перейти на новую строку в текущем блоке красивого вывода.
Красивый принтер должен разбить строку в этой точке,
Не обычный способ красивого вывода, поскольку принудительное разбиение строк может повлиять на текущие счетчики строк и вычисление размера блока. Использование подсказок для переноса строк внутри вложенного вертикального блока — лучший вариант.
val pp_print_if_newline : formatter -> unit -> unit
val print_if_newline : unit -> unit
Выполнить следующую команду форматирования, если предыдущая строка была только что разделена. В противном случае пропустить следующую команду форматирования.
Завершение красивого вывода
val pp_print_flush : formatter -> unit -> unit
val print_flush : unit -> unit
Конец красивого вывода: возвращает красивого принтера к начальному состоянию.
Все открытые блоки красивого вывода закрываются, весь ожидающий текст выводится. Кроме того, устройство вывода низкого уровня красивого принтера очищается, чтобы убедиться, что весь ожидающий текст действительно отображается.
Примечание: никогда не используйте print_flush в обычном ходе красивого вывода, поскольку красивейший принтер использует сложную механику буферизации для правильного отступа вывода; ручное очищение этих буферов случайным образом противоречит стратегии красивого принтера и приведет к плохой отрисовке.
Рассматривайте использование print_flush только в тех случаях, когда отобразить весь ожидающий материал обязательно (например, в случае интерактивного использования, когда вы хотите, чтобы пользователь прочитал некоторый текст), и когда сброс состояния красивого принтера не повлияет на дальнейший красивый вывод.
Предупреждение: Если устройство вывода красивого принтера является каналом вывода, повторные вызовы print_flush означают повторные вызовы flush для очистки канала вывода; эти явные вызовы очистки могут нарушить стратегию буферизации каналов вывода и могут значительно повлиять на эффективность.
val pp_print_newline : formatter -> unit -> unit
val print_newline : unit -> unit
Конец красивого вывода: возвращает красивого принтера к начальному состоянию.
Все открытые блоки красивого вывода закрываются, весь ожидающий текст выводится.
Эквивалентно Format.print_flush с выводом новой строки на устройстве вывода низкого уровня красивого принтера непосредственно перед очисткой устройства. См. соответствующие предупреждения для Format.print_flush.
Примечание: это не стандартный способ вывода новой строки; предпочтительный метод — использование подсказок для переноса строк внутри вертикального блока красивого вывода.
Отступ
val pp_infinity : int
pp_infinity — это максимальный размер отступа. Его точное значение зависит от реализации, но гарантируется, что он больше 109.
- Since 5.2
val pp_set_margin : formatter -> int -> unit
val set_margin : int -> unit
pp_set_margin ppf d устанавливает правый отступ до d (в символах): красивейший принтер разбивает строки, выходящие за пределы правого отступа, согласно заданным подсказкам переноса строк. Установка отступа в d означает, что движок форматирования стремится выводить не более d-1 символов на строку. Ничего не происходит, если d меньше 2. Если d >= Format.pp_infinity, правый отступ устанавливается на Format.pp_infinity - 1. Если d меньше текущего максимального предела отступа, максимальный предел отступа уменьшается, пытаясь сохранить минимальное соотношение max_indent/margin>=50% и при возможности текущую разницу margin - max_indent.
См. также Format.pp_set_geometry.
val pp_get_margin : formatter -> unit -> int
val get_margin : unit -> int
Возвращает позицию правого отступа.
Максимальный предел отступа
val pp_set_max_indent : formatter -> int -> unit
val set_max_indent : int -> unit
pp_set_max_indent ppf d устанавливает максимальный предел отступа строк на d (в символах): как только этот предел достигается, новые блоки красивого вывода отклоняются влево, если только вложенный блок полностью помещается в текущей строке. В качестве иллюстрации,
set_margin 10; set_max_indent 5; printf "@[123456@[7@]89A@]@."
дает
123456
789A
потому что вложенный блок "@[7@]" открывается после максимального предела отступа (7>5) и его родительский блок не помещается в текущей строке. Либо уменьшить длину родительского блока, чтобы он поместился в строку:
printf "@[123456@[7@]89@]@."
или открыть промежуточный блок перед максимальным пределом отступа, который помещается в текущей строке
printf "@[123@[456@[7@]89@]A@]@."
избегает отклонения внутренних блоков влево и выводит соответственно "123456789" и "123456789A" . Также обратите внимание, что вертикальные блоки никогда не помещаются в строку, а горизонтальные блоки всегда полностью помещаются в текущей строке. Открытие блока может разбить строку, даже если содержимое могло поместиться. Если это поведение проблематично, его можно устранить, установив максимальный предел отступа на margin - 1. Обратите внимание, что установка максимального предела отступа на margin недопустима.
Ничего не происходит, если d меньше 2.
Если d больше текущего отступа, он игнорируется, и текущий максимальный предел отступа сохраняется.
См. также Format.pp_set_geometry.
val pp_get_max_indent : formatter -> unit -> int
val get_max_indent : unit -> int
Возвращает максимальный предел отступа (в символах).
Геометрия
Геометрические функции могут использоваться для одновременного управления связанными переменными, отступом и максимальным пределом отступа.
type geometry = {
max_indent :
| |
margin :
|
} - Since 4.08
val check_geometry : geometry -> bool
Проверить, является ли геометрия форматировщика допустимой: 1 < max_indent < margin < Format.pp_infinity
- Since 4.08
val pp_set_geometry : formatter -> max_indent:int -> margin:int -> unit
val set_geometry : max_indent:int -> margin:int -> unit
val pp_safe_set_geometry : formatter -> max_indent:int -> margin:int -> unit
val safe_set_geometry : max_indent:int -> margin:int -> unit
pp_set_geometry ppf ~max_indent ~margin устанавливает и отступ, и максимальный предел отступа для ppf.
Когда 1 < max_indent < margin < Format.pp_infinity, pp_set_geometry ppf ~max_indent ~margin эквивалентно pp_set_margin ppf margin; pp_set_max_indent ppf max_indent; и избегает неявно неправильного pp_set_max_indent ppf max_indent; pp_set_margin ppf margin;
Вне этого диапазона, pp_set_geometry вызывает исключение неверного аргумента, в то время как pp_safe_set_geometry ничего не делает.
- Since 4.08
val pp_update_geometry : formatter -> (geometry -> geometry) -> unit
pp_update_geometry ppf (fun geo -> { geo with ... }) позволяет вам обновлять геометрию форматировщика надежным способом, который устойчив к расширению записи geometry новыми полями.
Вызывает исключение неверного аргумента, если возвращаемая геометрия не соответствует Format.check_geometry.
- Since 4.11
val update_geometry : (geometry -> geometry) -> unit
val pp_get_geometry : formatter -> unit -> geometry
val get_geometry : unit -> geometry
Возвращает текущую геометрию форматировщика.
- Since 4.08
Максимальная глубина форматирования
Максимальная глубина форматирования — это максимальное количество одновременно открытых блоков красивого вывода.
Материал внутри блоков, вложенных глубже, печатается как многоточие (точнее, как текст, возвращаемый Format.get_ellipsis_text ()).
val pp_set_max_boxes : formatter -> int -> unit
val set_max_boxes : int -> unit
pp_set_max_boxes ppf max устанавливает максимальное количество одновременно открытых блоков красивого вывода.
Материал внутри блоков, вложенных глубже, печатается как многоточие (точнее, как текст, возвращаемый Format.get_ellipsis_text ()).
Ничего не происходит, если max меньше 2.
val pp_get_max_boxes : formatter -> unit -> int
val get_max_boxes : unit -> int
Возвращает максимальное количество блоков красивого вывода, разрешенное перед многоточием.
val pp_over_max_boxes : formatter -> unit -> bool
val over_max_boxes : unit -> bool
Проверяет, были ли уже открыты максимальное количество блоков красивого вывода.
Табулирующие блоки
Табулирующий блок печатает материал на строках, разделённых на ячейки фиксированной длины. Табулирующий блок предоставляет простой способ отображения вертикальных столбцов выровненного по левому краю текста.
Этот блок содержит команду set_tab для определения границ ячеек и команду print_tab для перехода от ячейки к ячейке и разбиения строки, когда больше нет ячеек для печати в строке.
Примечание: печать внутри табулирующего блока направлена по строкам, поэтому произвольное разбиение строк внутри табулирующего блока приводит к плохому отображению. Тем не менее, контролируемое использование табулирующих блоков позволяет просто печатать столбцы в модуле Format.
val pp_open_tbox : formatter -> unit -> unit
val open_tbox : unit -> unit
open_tbox () открывает новый табулирующий блок.
Этот блок печатает строки, разделённые на ячейки фиксированной ширины.
Внутри табулирующего блока специальные табулирующие маркеры определяют точки интереса на строке (например, для определения границ ячеек). Функция Format.set_tab устанавливает табулирующий маркер в точке вставки.
Табулирующий блок содержит специальные разрывы табуляции для перехода к следующему табулирующему маркеру или разбиения строки. Функция Format.print_tbreak печатает разрыв табуляции.
val pp_close_tbox : formatter -> unit -> unit
val close_tbox : unit -> unit
Закрывает самый недавно открытый табулирующий блок.
val pp_set_tab : formatter -> unit -> unit
val set_tab : unit -> unit
Устанавливает табулирующий маркер в текущей точке вставки.
val pp_print_tab : formatter -> unit -> unit
val print_tab : unit -> unit
print_tab () отправляет подсказку о разрыве табуляции «следующий»: если он ещё не установлен на табулирующем маркере, точка вставки перемещается к первому табулирующему маркеру справа, или печатающее устройство разбивает строку, а точка вставки перемещается к левому табулирующему маркеру.
Это эквивалентно print_tbreak 0 0.
val pp_print_tbreak : formatter -> int -> int -> unit
val print_tbreak : int -> int -> unit
print_tbreak nspaces offset отправляет подсказку о разрыве табуляции «полный».
Если он ещё не установлен на табулирующем маркере, точка вставки перемещается к первому табулирующему маркеру справа, и печатающее устройство печатает nspaces пробелов.
Если справа нет следующего табулирующего маркера, печатающее устройство разбивает строку в этой точке, а затем точка вставки перемещается к самому левому табулирующему маркеру блока.
Если печатающее устройство разбивает строку, к текущему отступу добавляется offset.
Многоточие
val pp_set_ellipsis_text : formatter -> string -> unit
val set_ellipsis_text : string -> unit
Устанавливает текст многоточия, печатаемого, когда открыто слишком много блоков красивого вывода (по умолчанию — одна точка, .).
val pp_get_ellipsis_text : formatter -> unit -> string
val get_ellipsis_text : unit -> string
Возвращает текст многоточия.
Семантические теги
type stag = ..
Семантические теги (или просто теги) — это определяемые пользователем аннотации, которые связывают специфические операции пользователя с напечатанными сущностями.
Общее использование семантических тегов — это декорация текста для получения специфического отображения шрифта или размера текста на устройстве отображения или маркировка границ сущностей (например, HTML или TeX-элементов или последовательностей экранирования терминала). Более изощрённое использование семантических тегов может обрабатывать динамические модификации поведения печатающего устройства для правильной печати материала внутри некоторых специфических тегов. Например, мы можем определить тег RGB следующим образом:
type stag += RGB of {r:int;g:int;b:int}
Для правильной разграничения напечатанных сущностей семантический тег должен открываться перед сущностью и закрываться после неё. Семантические теги должны быть правильно вложены, как скобки, с использованием Format.pp_open_stag и Format.pp_close_stag.
Операции, специфичные для тегов, происходят всякий раз, когда тег открывается или закрывается. При каждом возникновении выполняются два типа операций: разметка тега и печать тега:
- Операция разметки тега — это более простая операция, специфичная для тега: она просто записывает строку, специфичную для тега, в устройство вывода форматировщика. Разметка тега не влияет на вычисление разбиения строк.
- Операция печати тега — это более сложная операция, специфичная для тега: она может печатать произвольный материал в форматировщике. Печать тега тесно связана с текущими операциями печатающего устройства.
Грубо говоря, разметка тега обычно используется для лучшего отображения текста на устройстве вывода, а печать тега позволяет точно настраивать процедуры печати, чтобы печатать одну и ту же сущность по-разному в зависимости от семантических тегов (т.е. печатать дополнительный материал или даже пропускать части вывода).
Точнее: когда семантический тег открывается или закрывается, выполняются как «печать тега», так и последующие операции «разметки тега»:
- Печать семантического тега означает вызов специфической для форматировщика функции
print_open_stag(соответственноprint_close_stag) с именем тега в качестве аргумента: эта функция печати тега может затем печатать любой обычный материал в форматировщике (так что этот материал добавляется в очередь форматировщика для дальнейших вычислений разбиения строк). - Разметка семантического тега означает вызов специфической для форматировщика функции
mark_open_stag(соответственноmark_close_stag) с именем тега в качестве аргумента: эта функция разметки тега может затем вернуть «отметку открытия тега» (соответственно «отметку закрытия тега») для непосредственной записи в устройство вывода форматировщика.
Поскольку строки маркеров семантических тегов записываются непосредственно в устройство вывода форматировщика, они не рассматриваются как часть печатного материала, управляющего разбиением строк (другими словами, длина строк, соответствующих маркерам тегов, считается равной нулю для разбиения строк).
Таким образом, обработка семантических тегов в некотором смысле прозрачна для красивого вывода и не влияет на обычные отступы. Следовательно, одна и та же процедура красивого вывода может выводить как простой «verbatim» материал, так и более богатый оформленный вывод в зависимости от обработки тегов. По умолчанию теги не активны, поэтому вывод не украшен информацией о тегах. Как только set_tags устанавливается на true, движок красивого вывода учитывает теги и соответствующим образом оформляет вывод.
Функции разметки тегов по умолчанию ведут себя по-HTML: теги строк строковые теги заключены в «<» и «>», а другие теги игнорируются; следовательно, открывающая метка для тега строки "t" — "<t>", а закрывающая — "</t>".
Функции печати тегов по умолчанию ничего не делают.
Функции разметки и печати тегов можно определять пользователю и настраивать, вызвав Format.set_formatter_stag_functions.
Операции с семантическими тегами могут быть включены или выключены с помощью Format.set_tags. Операции разметки тегов могут быть включены или выключены с помощью Format.set_mark_tags. Операции печати тегов могут быть включены или выключены с помощью Format.set_print_tags.
- Since 4.08
type tag = string
type stag +=
|
| String_tag of
| (* |
|
*) |
val pp_open_stag : formatter -> stag -> unit
val open_stag : stag -> unit
pp_open_stag ppf t открывает семантический тег с именем t.
Функция print_open_stag печати тегов форматировщика вызывается с t в качестве аргумента; затем отметка открытия тега для t, как указано в mark_open_stag t, записывается в устройство вывода форматировщика.
- Since 4.08
val pp_close_stag : formatter -> unit -> unit
val close_stag : unit -> unit
pp_close_stag ppf () закрывает самый недавно открытый семантический тег t.
Закрывающая метка, как указано в mark_close_stag t, записывается в устройство вывода форматировщика; затем функция print_close_stag печати тегов форматировщика вызывается с t в качестве аргумента.
- Since 4.08
val pp_set_tags : formatter -> bool -> unit
val set_tags : bool -> unit
pp_set_tags ppf b включает или выключает обработку семантических тегов (по умолчанию — выключено).
val pp_set_print_tags : formatter -> bool -> unit
val set_print_tags : bool -> unit
pp_set_print_tags ppf b включает или выключает операции печати тегов.
val pp_set_mark_tags : formatter -> bool -> unit
val set_mark_tags : bool -> unit
pp_set_mark_tags ppf b включает или выключает операции разметки тегов.
val pp_get_print_tags : formatter -> unit -> bool
val get_print_tags : unit -> bool
Возвращает текущий статус операций печати тегов.
val pp_get_mark_tags : formatter -> unit -> bool
val get_mark_tags : unit -> bool
Возвращает текущий статус операций маркировки тегов.
val pp_set_formatter_out_channel : formatter -> out_channel -> unit
Перенаправление стандартного вывода форматировщика
val set_formatter_out_channel : out_channel -> unit
Перенаправляет стандартный вывод красивого принтера на указанный канал. (Все функции вывода стандартного форматировщика устанавливаются на функции по умолчанию, печатающие в заданный канал.)
set_formatter_out_channel эквивалентно Format.pp_set_formatter_out_channel std_formatter.
val pp_set_formatter_output_functions : formatter -> (string -> int -> int -> unit) -> (unit -> unit) -> unit
val set_formatter_output_functions : (string -> int -> int -> unit) -> (unit -> unit) -> unit
pp_set_formatter_output_functions ppf out flush перенаправляет стандартные функции вывода красивого принтера на функции out и flush.
Функция out выполняет весь вывод строк красивого принтера. Она вызывается со строкой s, начальной позицией p и количеством символов n; она должна вывести символы p по p + n - 1 из s.
Функция flush вызывается всякий раз, когда красивого принтер сбрасывается (через преобразование %!, или указания красивого печатания @? или @., или с помощью функций низкого уровня print_flush или print_newline).
val pp_get_formatter_output_functions : formatter -> unit -> (string -> int -> int -> unit) * (unit -> unit)
val get_formatter_output_functions : unit -> (string -> int -> int -> unit) * (unit -> unit)
Возвращает текущие функции вывода стандартного красивого принтера.
Переопределение вывода форматировщика
Модуль Format достаточно универсален, чтобы позволить вам полностью переопределить смысл вывода красивого принтера: вы можете предоставить свои собственные функции, чтобы определить, как обрабатывать отступы, разделение строк и даже печать всех символов, которые должны быть напечатаны!
Переопределение функций вывода
type formatter_out_functions = {
out_string :
| ||||
out_flush :
| ||||
out_newline :
| ||||
out_spaces :
| ||||
out_indent :
| (* |
|
*) |
} Набор функций вывода, специфичных для форматировщика:
- функция
out_stringвыполняет весь вывод строк красивого принтера. Она вызывается со строкойs, начальной позициейpи количеством символовn; она должна вывести символыpпоp + n - 1изs. - функция
out_flushсбрасывает устройство вывода красивого принтера. -
out_newlineвызывается для открытия новой строки, когда красивого принтер разделяет строку. - функция
out_spacesвыводит пробелы, когда подсказка разрыва приводит к пробелам вместо разрыва строки. Она вызывается с количеством пробелов для вывода. - функция
out_indentвыполняет отступ новой строки, когда красивого принтер разделяет строку. Она вызывается со значением отступа новой строки.
По умолчанию:
- поля
out_stringиout_flushзависят от устройства вывода; (например,output_stringиflushдля устройстваout_channel, илиBuffer.add_substringиignoreдля устройства выводаBuffer.t), - поле
out_newlineэквивалентноout_string "\n" 0 1; - поля
out_spacesиout_indentэквивалентныout_string (String.make n ' ') 0 n.
- Since 4.01
val pp_set_formatter_out_functions : formatter -> formatter_out_functions -> unit
val set_formatter_out_functions : formatter_out_functions -> unit
pp_set_formatter_out_functions ppf out_funs Устанавливает все функции вывода красивого принтера ppf на те из аргумента out_funs,
Таким образом, вы можете изменить смысл отступов (который может быть чем-то другим, чем просто печать символов пробела) и смысл открытия новых строк (который может быть связан с любым другим действием, необходимым текущему применению).
Разумные значения по умолчанию для функций out_spaces и out_newline соответственно out_funs.out_string (String.make n ' ') 0 n и out_funs.out_string "\n" 0 1.
- Since 4.01
val pp_get_formatter_out_functions : formatter -> unit -> formatter_out_functions
val get_formatter_out_functions : unit -> formatter_out_functions
Возвращает текущие функции вывода красивого принтера, включая функции разделения строк и отступов. Полезно для записи текущих настроек и восстановления их позже.
- Since 4.01
Переопределение операций с тегами семантики
type formatter_stag_functions = {
mark_open_stag :
| |
mark_close_stag :
| |
print_open_stag :
| |
print_close_stag :
|
} Функции обработки тегов семантики, специфичные для форматировщика: версии mark — это функции «маркировки тегов», которые связывают строковый маркер с тегом, чтобы движок красивого принтера записал эти маркеры как токены длиной 0 в устройстве вывода форматировщика. Версии print — это функции «печати тегов», которые могут выполнять обычную печать, когда тег закрывается или открывается.
- Since 4.08
val pp_set_formatter_stag_functions : formatter -> formatter_stag_functions -> unit
val set_formatter_stag_functions : formatter_stag_functions -> unit
pp_set_formatter_stag_functions ppf tag_funs изменяет смысл операций открытия и закрытия семантических тегов на использование функций в tag_funs при печати на ppf.
При открытии семантического тега с именем t, строка t передается функции маркировки открывающего тега (поле mark_open_stag записи tag_funs), которая должна вернуть маркер открывающего тега для этого имени. Когда происходит следующий вызов close_stag (), имя семантического тега t отправляется обратно функции маркировки закрывающего тега (поле mark_close_stag записи tag_funs), которая должна вернуть маркер закрывающего тега для этого имени.
Поле print_ записи содержит функции печати тегов, которые вызываются во время открытия и закрытия тегов, чтобы выводить обычный материал в очереди красивого принтера.
- Since 4.08
val pp_get_formatter_stag_functions : formatter -> unit -> formatter_stag_functions
val get_formatter_stag_functions : unit -> formatter_stag_functions
Возвращает текущие функции операций с семантическими тегами стандартного красивого принтера.
- Since 4.08
Определение форматировщиков
Определение новых форматировщиков позволяет параллельно выводить материал на несколько устройств вывода. Все параметры форматировщика локальны для форматировщика: правая граница, максимальный предел отступа, максимальное количество одновременно открытых блоков красивого принтера, многоточие и т. д. специфичны для каждого форматировщика и могут быть установлены независимо.
Например, с учетом буфера Buffer.t b, Format.formatter_of_buffer b возвращает новый форматировщик, использующий буфер b в качестве устройства вывода. Аналогично, с учетом канала вывода out_channel oc, Format.formatter_of_out_channel oc возвращает новый форматировщик, использующий канал oc в качестве устройства вывода.
В качестве альтернативы, с учетом out_funs, полного набора функций вывода для форматировщика, Format.formatter_of_out_functions out_funs вычисляет новый форматировщик, использующий эти функции для вывода.
val formatter_of_out_channel : out_channel -> formatter
formatter_of_out_channel oc возвращает новый форматировщик, записывающий в соответствующий канал вывода oc.
val synchronized_formatter_of_out_channel : out_channel -> formatter Domain.DLS.key
synchronized_formatter_of_out_channel oc возвращает ключ к доменному локальному состоянию, которое содержит доменно-локальный форматировщик для записи в соответствующий канал вывода oc.
При использовании форматировщика с несколькими доменам вывод из доменов будет переплетен между собой в моменты сброса форматировщика, например, с помощью Format.print_flush.
- Alert нестабильно.
val std_formatter : formatter
Стандартный форматировщик начального домена для записи в стандартный вывод.
Он определен как Format.formatter_of_out_channel stdout.
val get_std_formatter : unit -> formatter
get_std_formatter () возвращает текущий стандартный форматировщик домена, используемый для записи в стандартный вывод.
- Since 5.0
val err_formatter : formatter
Форматировщик начального домена для записи в стандартный вывод ошибок.
Он определен как Format.formatter_of_out_channel stderr.
val get_err_formatter : unit -> formatter
get_err_formatter () возвращает форматировщик текущего домена, используемый для записи в стандартный поток ошибок.
- Since 5.0
val formatter_of_buffer : Buffer.t -> formatter
formatter_of_buffer b возвращает новый форматировщик, записывающий в буфер b. В конце красивой печати форматировщик должен быть сброшен, используя Format.pp_print_flush или Format.pp_print_newline, чтобы напечатать все ожидающие данные в буфер.
val stdbuf : Buffer.t
Начальный строковый буфер домена, в который str_formatter записывает.
val get_stdbuf : unit -> Buffer.t
get_stdbuf () возвращает текущий строковый буфер домена, в который записывает текущий строковый форматировщик домена.
- Since 5.0
val str_formatter : formatter
Начальный форматировщик домена для вывода в Format.stdbuf строковый буфер.
str_formatter определяется как Format.formatter_of_buffer Format.stdbuf.
val get_str_formatter : unit -> formatter
Текущий форматировщик домена для вывода в строковый буфер текущего домена.
- Since 5.0
val flush_str_formatter : unit -> string
Возвращает материал, напечатанный с помощью str_formatter текущего домена, сбрасывает форматировщик и сбрасывает соответствующий буфер.
val make_formatter : (string -> int -> int -> unit) -> (unit -> unit) -> formatter
make_formatter out flush возвращает новый форматировщик, который выводит с функцией out, и сбрасывает с функцией flush.
Например,
make_formatter
(Stdlib.output_substring oc)
(fun () -> Stdlib.flush oc)
возвращает форматировщик в out_channel oc.
val make_synchronized_formatter : (string -> int -> int -> unit) -> (unit -> unit) -> formatter Domain.DLS.key
make_synchronized_formatter out flush возвращает ключ к локальному состоянию домена, который содержит локальный форматировщик домена, который выводит с помощью функции out, и сбрасывает с функцией flush.
Когда форматировщик используется с несколькими доменами, вывод из доменов будет чередоваться друг с другом в точках, где форматировщик сбрасывается, например, с помощью Format.print_flush.
- Since 5.0
- Alert unstable.
val formatter_of_out_functions : formatter_out_functions -> formatter
formatter_of_out_functions out_funs возвращает новый форматировщик, который записывает с набором функций вывода out_funs.
См. определение типа Format.formatter_out_functions для значения аргумента out_funs.
- Since 4.06
Символьная красивая печать
Символьная красивая печать — это красивая печать с использованием символьного форматировщика, т. е. форматировщика, который выводит символьные элементы красивой печати.
При использовании символьного форматировщика все обычные операции красивой печати происходят, но вывод материала является символическим и хранится в буфере выходных элементов. В конце красивой печати сброс буфера вывода позволяет обработать символьный вывод перед выполнением операций низкого уровня вывода.
На практике сначала определите символьный буфер вывода b с помощью:
-
let sob = make_symbolic_output_buffer (). Затем определите символьный форматировщик с помощью: let ppf = formatter_of_symbolic_output_buffer sob
Используйте символьный форматировщик ppf как обычно, и получите символьные элементы в конце красивой печати, сбросив символьный буфер вывода sob с помощью:
-
flush_symbolic_output_buffer sob.
type symbolic_output_item =
|
| Output_flush
| (* |
команда сброса символьного вывода |
*) |
|
| Output_newline
| (* |
команда символьной новой строки |
*) |
|
| Output_string of
| (* |
|
*) |
|
| Output_spaces of
| (* |
|
*) |
|
| Output_indent of
| (* |
|
*) |
Элементы, созданные символьными средствами красивой печати
- Since 4.06
type symbolic_output_buffer
Буфер вывода символьного средства красивой печати.
- Since 4.06
val make_symbolic_output_buffer : unit -> symbolic_output_buffer
make_symbolic_output_buffer () возвращает свежий буфер для символьного вывода.
- Since 4.06
val clear_symbolic_output_buffer : symbolic_output_buffer -> unit
clear_symbolic_output_buffer sob сбрасывает буфер sob.
- Since 4.06
val get_symbolic_output_buffer : symbolic_output_buffer -> symbolic_output_item list
get_symbolic_output_buffer sob возвращает содержимое буфера sob.
- Since 4.06
val flush_symbolic_output_buffer : symbolic_output_buffer -> symbolic_output_item list
flush_symbolic_output_buffer sob возвращает содержимое буфера sob и сбрасывает буфер sob. flush_symbolic_output_buffer sob эквивалентно let items = get_symbolic_output_buffer sob in
clear_symbolic_output_buffer sob; items
- Since 4.06
val add_symbolic_output_item : symbolic_output_buffer -> symbolic_output_item -> unit
add_symbolic_output_item sob itm добавляет элемент itm в буфер sob.
- Since 4.06
val formatter_of_symbolic_output_buffer : symbolic_output_buffer -> formatter
formatter_of_symbolic_output_buffer sob возвращает символьный форматировщик, который выводит в symbolic_output_buffer sob.
- Since 4.06
Функции удобной форматирования.
val pp_print_iter : ?pp_sep:(formatter -> unit -> unit) -> (('a -> unit) -> 'b -> unit) -> (formatter -> 'a -> unit) -> formatter -> 'b -> unit
pp_print_iter ~pp_sep iter pp_v ppf v форматирует на ppf итерации iter по коллекции v значений, используя pp_v. Итерации разделяются pp_sep (по умолчанию Format.pp_print_cut).
- Since 5.1
val pp_print_list : ?pp_sep:(formatter -> unit -> unit) -> (formatter -> 'a -> unit) -> formatter -> 'a list -> unit
pp_print_list ?pp_sep pp_v ppf l печатает элементы списка l, используя pp_v для печати каждого элемента и вызывая pp_sep между элементами (pp_sep по умолчанию Format.pp_print_cut). Ничего не делает для пустых списков.
- Since 4.02
val pp_print_array : ?pp_sep:(formatter -> unit -> unit) -> (formatter -> 'a -> unit) -> formatter -> 'a array -> unit
pp_print_array ?pp_sep pp_v ppf a печатает элементы массива a, используя pp_v для печати каждого элемента и вызывая pp_sep между элементами (pp_sep по умолчанию Format.pp_print_cut). Ничего не делает для пустых массивов.
Если a изменяется после вызова pp_print_array, напечатанные значения могут отличаться от ожидаемых, потому что Format может задерживать печать. Этого можно избежать, сбросив ppf.
- Since 5.1
val pp_print_seq : ?pp_sep:(formatter -> unit -> unit) -> (formatter -> 'a -> unit) -> formatter -> 'a Seq.t -> unit
pp_print_seq ?pp_sep pp_v ppf s печатает элементы последовательности s, используя pp_v для печати каждого элемента и вызывая pp_sep между элементами (pp_sep по умолчанию Format.pp_print_cut). Ничего не делает для пустых последовательностей.
Эта функция не завершается для бесконечных последовательностей.
- Since 4.12
val pp_print_text : formatter -> string -> unit
pp_print_text ppf s печатает s с пробелами и новой строкой, напечатанными с помощью Format.pp_print_space и Format.pp_force_newline.
- Since 4.02
val pp_print_option : ?none:(formatter -> unit -> unit) -> (formatter -> 'a -> unit) -> formatter -> 'a option -> unit
pp_print_option ?none pp_v ppf o печатает o на ppf с помощью pp_v если o равно Some v и none если оно равно None. none по умолчанию ничего не печатает.
- Since 4.08
val pp_print_result : ok:(formatter -> 'a -> unit) -> error:(formatter -> 'e -> unit) -> formatter -> ('a, 'e) result -> unit
pp_print_result ~ok ~error ppf r печатает r на ppf с помощью ok если r равно Ok _ и error если r равно Error _.
- Since 4.08
val pp_print_either : left:(formatter -> 'a -> unit) -> right:(formatter -> 'b -> unit) -> formatter -> ('a, 'b) Either.t -> unit
pp_print_either ~left ~right ppf e печатает e на ppf с помощью left если e равно Either.Left _ и right если e равно Either.Right _.
- Since 4.13
Форматированный вывод
Модуль Format предоставляет полный набор функций printf для форматированного вывода с использованием спецификаций форматирования строк.
В строки форматирования могут быть добавлены специальные аннотации для предоставления команд форматирования вывода для двигателя форматирования вывода.
Эти аннотации вводятся в строки форматирования с использованием символа @. Например, @ означает пробел, @, означает разрыв, @[ открывает новый блок, а @] закрывает последний открытый блок.
val fprintf : formatter -> ('a, formatter, unit) format -> 'a
fprintf ff fmt arg1 ... argN форматирует аргументы arg1 в соответствии со строкой форматирования fmt, и выводит полученную строку на форматировщик ff.
Строка форматирования fmt — это строка символов, содержащая три типа объектов: обычные символы и спецификации преобразования, как указано в модуле Printf, и указания форматирования вывода, специфичные для модуля Format.
Символы форматирования вывода вводятся символом @ и имеют следующие значения:
-
@[: открывает блок форматирования вывода. Тип и смещение блока могут быть необязательно указаны с помощью следующего синтаксиса: символ<, за которым следует необязательное указание типа блока, затем необязательное целое смещение и закрывающий символ>Тип блока форматирования вывода может быть одним изh,v,hv,b, илиhov. 'h' обозначает 'горизонтальный' блок форматирования вывода, 'v' обозначает 'вертикальный' блок форматирования вывода, 'hv' обозначает 'горизонтально-вертикальный' блок форматирования вывода, 'b' обозначает 'горизонтально-или-вертикальный' блок форматирования вывода с отступом, 'hov' обозначает простой 'горизонтально-или-вертикальный' блок форматирования вывода. Например,@[<hov 2>открывает 'горизонтально-или-вертикальный' блок форматирования вывода с отступом 2, как получено сopen_hovbox 2. Более подробную информацию о блоках форматирования вывода см. в различных функциях открытия блоковopen_*box. -
@]: закрывает последний открытый блок форматирования вывода. -
@,: выводит подсказку разрыва 'разрыв', как вprint_cut (). -
@: выводит подсказку разрыва 'пробел', как вprint_space (). -
@;: выводит подсказку разрыва 'полный', как вprint_break. Параметрыnspacesиoffsetподсказки разрыва могут быть необязательно указаны следующим образом: символ<, за которым следует целое значениеnspaces, затем целое значениеoffset, и закрывающий символ>Если параметры не указаны, подсказка полного разрыва по умолчанию — подсказка разрыва 'пробел'. -
@.: очищает форматировщик вывода и разделяет строку, как вprint_newline (). -
@<n>: выводит следующий элемент, как если бы его длина былаn. Следовательно,printf "@<0>%s" argвыводитargкак строку нулевой длины. Если@<n>не сопровождается спецификацией преобразования, то следующий символ формата выводится как имеющий длинуn. -
@{: открывает тег семантики. Имя тега может быть необязательно указано с помощью следующего синтаксиса: символ<, за которым следует необязательная строковая спецификация и закрывающий символ>Строковая спецификация — это любая строка символов, не содержащая закрывающий символ'>'Если она опущена, имя тега по умолчанию — пустая строка. Более подробную информацию о семантических тегах см. в функцияхFormat.open_stagиFormat.close_stag. -
@}: закрывает последний открытый тег семантики. -
@?: очищает форматировщик вывода, как вprint_flush ()Это эквивалентно преобразованию%!. -
@\n: принудительно переносит строку, как вforce_newline (), а не обычным способом форматирования вывода. Следует отдавать предпочтение использованию подсказок разрыва внутри вертикального блока форматирования вывода.
Примечание: Чтобы предотвратить интерпретацию символа @ как указания форматирования вывода, экранируйте его символом %. Старый режим цитирования @@ устарел, так как он несовместим с интерпретацией в формате входных символов '@'.
Пример: printf "@[%s@ %d@]@." "x =" 1 эквивалентно open_box (); print_string "x ="; print_space ();. Он печатает
print_int 1; close_box (); print_newline ()x = 1 в блоке форматирования вывода 'горизонтально-или-вертикально'.
val printf : ('a, formatter, unit) format -> 'a
То же, что и fprintf выше, но вывод на get_std_formatter ().
Оно определено аналогично fun fmt -> fprintf (get_std_formatter ()) fmt, но откладывает вызов get_std_formatter до получения последнего аргумента, необходимого для format. При использовании с несколькими областями вывод из областей будет переплетаться друг с другом в точках, где форматировщик очищается, например, с помощью Format.print_flush.
val eprintf : ('a, formatter, unit) format -> 'a
То же, что и fprintf выше, но вывод на get_err_formatter ().
Оно определено аналогично fun fmt -> fprintf (get_err_formatter ()) fmt, но откладывает вызов get_err_formatter до получения последнего аргумента, необходимого для format При использовании с несколькими областями вывод из областей будет переплетаться друг с другом в точках, где форматировщик очищается, например, с помощью Format.print_flush.
val sprintf : ('a, unit, string) format -> 'a
То же, что и printf выше, но вместо вывода на форматировщик возвращает строку, содержащую результат форматирования аргументов. Обратите внимание, что очередь форматирования вывода очищается в конце каждого вызова sprintf. Обратите внимание, что если ваша строка форматирования содержит %a, вам следует использовать asprintf.
В случае нескольких связанных вызовов sprintf для вывода материала в одной строке, следует рассмотреть использование fprintf с предопределенным форматировщиком str_formatter и вызов flush_str_formatter () для получения конечного результата.
В качестве альтернативы можно использовать Format.fprintf с форматировщиком, записывающим в буфер: очистка форматировщика и буфера в конце форматирования вывода возвращает желаемую строку.
val asprintf : ('a, formatter, unit, string) format4 -> 'a
То же, что и printf выше, но вместо вывода на форматировщик возвращает строку, содержащую результат форматирования аргументов. Тип asprintf достаточно общий, чтобы хорошо взаимодействовать с преобразованиями %a.
- Since 4.01
val dprintf : ('a, formatter, unit, formatter -> unit) format4 -> 'a
То же, что и Format.fprintf, за исключением того, что форматировщик является последним аргументом. dprintf "..." a b c — это функция типа formatter -> unit, которую можно передать спецификатору формата %t.
Это может быть использовано как замена Format.asprintf для отложенного принятия решений о форматировании. Использование возвращаемой строкой Format.asprintf в контексте форматирования заставляет принимать решения о форматировании изолированно, и окончательная строка может быть создана преждевременно. Format.dprintf позволяет отложить принятие решений о форматировании до тех пор, пока не будет известен окончательный контекст форматирования. Например:
let t = Format.dprintf "%i@ %i@ %i" 1 2 3 in ... Format.printf "@[<v>%t@]" t
- Since 4.08
val ifprintf : formatter -> ('a, formatter, unit) format -> 'a
То же, что и fprintf выше, но ничего не печатает. Полезно игнорировать некоторый материал при условном выводе.
- Since 3.10
Форматированный вывод с продолжениями.
val kfprintf : (formatter -> 'a) -> formatter -> ('b, formatter, unit, 'a) format4 -> 'b
То же, что и fprintf выше, но вместо немедленного возврата передает форматировщик в свой первый аргумент в конце вывода.
val kdprintf : ((formatter -> unit) -> 'a) -> ('b, formatter, unit, 'a) format4 -> 'b
То же, что и Format.dprintf выше, но вместо немедленного возврата передает приостановленный принтер в свой первый аргумент в конце вывода.
- Since 4.08
val ikfprintf : (formatter -> 'a) -> formatter -> ('b, formatter, unit, 'a) format4 -> 'b
То же, что и kfprintf выше, но ничего не печатает. Полезно игнорировать некоторый материал при условном выводе.
- Since 3.12
val ksprintf : (string -> 'a) -> ('b, unit, string, 'a) format4 -> 'b
То же, что и sprintf выше, но вместо возврата строки передает её в первый аргумент.
val kasprintf : (string -> 'a) -> ('b, formatter, unit, 'a) format4 -> 'b
То же самое, что и asprintf выше, но вместо возвращения строки, она передаётся в первый аргумент.
- С момента 4.03
Примеры
Несколько примеров для понимания того, как используется Format.
У нас есть список l пар (int * bool), которые отображаются для нас на верхнем уровне:
# let l = List.init 20 (fun n -> n, n mod 2 = 0) val l : (int * bool) list = [(0, true); (1, false); (2, true); (3, false); (4, true); (5, false); (6, true); (7, false); (8, true); (9, false); (10, true); (11, false); (12, true); (13, false); (14, true); (15, false); (16, true); (17, false); (18, true); (19, false)]
Если мы хотим вывести его сами без магических свойств верхнего уровня, мы можем попробовать так:
# let pp_pair out (x,y) = Format.fprintf out "(%d, %b)" x y
val pp_pair : Format.formatter -> int * bool -> unit = <fun>
# Format.printf "l: [@[<hov>%a@]]@."
Format.(pp_print_list ~pp_sep:(fun out () -> fprintf out ";@ ") pp_pair) l
l: [(0, true); (1, false); (2, true); (3, false); (4, true); (5, false);
(6, true); (7, false); (8, true); (9, false); (10, true); (11, false);
(12, true); (13, false); (14, true); (15, false); (16, true);
(17, false); (18, true); (19, false)]
Вкратце, это делает:
-
pp_pairвыводит паруbool*int, окружённую «( )». Она принимает форматировщик (в который происходит форматирование) и саму пару. После завершения вывода она возвращает().
-
Format.printf "l = [@[<hov>%a@]]@." ... lпохож наprintf, но с дополнительными инструкциями по форматированию (обозначенными «@»). Пара «@[<hov>» и «@]» представляет собой «горизонтальную или вертикальную область».
- «@.» завершает форматирование с новой строкой. Он похож на «\n», но также учитывает состояние
Format.formatter. Не используйте «\n» сFormat.
- «%a» — это инструкция по форматированию, аналогичная «%d» или «%s» для
printf. Однако, в то время как «%d» выводит целое число, а «%s» — строку, «%a» принимает принтер (типаFormat.formatter -> 'a -> unit) и значение (типа'a) и применяет принтер к значению. Это ключевой момент для композиционности принтеров.
- Мы создаём принтер списка с помощью
Format.pp_print_list ~pp_sep:(...) pp_pair.pp_print_listпринимает принтер элемента и возвращает принтер списка.?pp_sepнеобязательный аргумент, если предоставлен, вызывается между каждым элементом для печати разделителя.
- Здесь в качестве разделителя мы используем
(fun out () -> Format.fprintf out ";@ "). Он выводит «;», а затем «@ » — это разделительный пробел (либо он выводит « », либо он выводит новую строку, если область собирается переполниться). Этот «@ » отвечает за разбиение вывода списка на несколько строк.
Если мы опустим «@ », получим некрасивый вывод в одной строке:
# Format.printf "l: [@[<hov>%a@]]@."
Format.(pp_print_list ~pp_sep:(fun out () -> fprintf out "; ") pp_pair) l
l: [(0, true); (1, false); (2, true); (* ... *); (18, true); (19, false)]
- : unit = ()
В целом, рекомендуется определять пользовательские принтеры для важных типов в вашей программе. Например, если вы определите базовые типы геометрии следующим образом:
type point = {
x: float;
y: float;
}
type rectangle = {
ll: point; (* lower left *)
ur: point; (* upper right *)
}
Для целей отладки, отображения информации в логах или на консоли было бы удобно определить принтеры для этих типов. Вот пример того, как это сделать. Обратите внимание, что «%.3f» — это принтер float до 3 цифр после запятой; «%f» выводил бы столько цифр, сколько требуется, что несколько громоздко; «%h» — принтер шестнадцатеричных чисел с плавающей запятой.
let pp_point out (p:point) =
Format.fprintf out "{ @[x=%.3f;@ y=%.3f@] }" p.x p.y
let pp_rectangle out (r:rectangle) =
Format.fprintf out "{ @[ll=%a;@ ur=%a@] }"
pp_point r.ll pp_point r.ur
В файле .mli мы могли бы иметь:
val pp_point : Format.formatter -> point -> unit
val pp_rectangle : Format.formatter -> rectangle -> unit
Теперь эти принтеры можно использовать с «%a» внутри других принтеров.
# Format.printf "some rectangle: %a@."
(Format.pp_print_option pp_rectangle)
(Some {ll={x=1.; y=2.}; ur={x=42.; y=500.12345}})
some rectangle: { l={ x=1.000; y=2.000 }; ur={ x=42.000; y=500.123 } }
# Format.printf "no rectangle: %a@."
(Format.pp_option pp_rectangle)
None
no rectangle:
Посмотрите, как мы комбинируем pp_print_option (принтер опций) и наш недавно определённый принтер прямоугольников, как мы делали с pp_print_list ранее.
Для более подробного руководства, см. «Использование модуля Format».
Окончательное замечание: модуль Format — это отправная точка. Экосистема OCaml имеет библиотеки, которые упрощают и делают форматирование более выразительным, с более гибкими комбинаторами, более лаконичными именами и т. д. Примером такой библиотеки является Fmt.
Также возможно автоматическое получение красивых принтеров из определений типов, используя https://github.com/ocaml-ppx/ppx_deriving или аналогичные ppx-дериваторы.
© 1995-2024 INRIA.
https://ocaml.org/manual/5.2/api/Format.html