]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libxo/libxo/xo_format.5
Upgrade to Unbound 1.5.4.
[FreeBSD/FreeBSD.git] / contrib / libxo / libxo / xo_format.5
1 .\" #
2 .\" # Copyright (c) 2014, Juniper Networks, Inc.
3 .\" # All rights reserved.
4 .\" # This SOFTWARE is licensed under the LICENSE provided in the
5 .\" # ../Copyright file. By downloading, installing, copying, or
6 .\" # using the SOFTWARE, you agree to be bound by the terms of that
7 .\" # LICENSE.
8 .\" # Phil Shafer, July 2014
9 .\"
10 .Dd December 4, 2014
11 .Dt LIBXO 3
12 .Os
13 .Sh NAME
14 .Nm xo_format
15 .Nd content of format descriptors for xo_emit
16 .Sh DESCRIPTION
17 .Pp
18 .Nm libxo
19 uses format strings to control the rendering of data into
20 various output styles, including
21 .Em text ,
22 .Em XML ,
23 .Em JSON ,
24 and
25 .Em HTML .
26 Each format string contains a set of zero or more
27 .Dq "field descriptions" ,
28 which describe independent data fields.
29 Each field description contains a set of
30 .Dq modifiers ,
31 a
32 .Dq "content string" ,
33 and zero, one, or two
34 .Dq "format descriptors" .
35 The modifiers tell
36 .Nm libxo
37 what the field is and how to treat it, while the format descriptors are
38 formatting instructions using
39 .Xr printf 3 Ns -style
40 format strings, telling
41 .Nm libxo
42 how to format the field.
43 The field description is placed inside
44 a set of braces, with a colon
45 .Ql ( \&: )
46 after the modifiers and a slash
47 .Ql ( \&/ )
48 before each format descriptors.
49 Text may be intermixed with
50 field descriptions within the format string.
51 .Pp
52 The field description is given as follows:
53 .Bd -literal -offset indent
54     '{' [ role | modifier ]* [',' long-names ]* ':' [ content ]
55             [ '/' field-format [ '/' encoding-format ]] '}'
56 .Ed
57 .Pp
58 The role describes the function of the field, while the modifiers
59 enable optional behaviors.
60 The contents, field-format, and
61 encoding-format are used in varying ways, based on the role.
62 These are described in the following sections.
63 .Pp
64 Braces can be escaped by using double braces, similar to "%%" in
65 .Xr printf 3 .
66 The format string "{{braces}}" would emit "{braces}".
67 .Pp
68 In the following example, three field descriptors appear.
69 The first
70 is a padding field containing three spaces of padding, the second is a
71 label ("In stock"), and the third is a value field ("in-stock").
72 The in-stock field has a "%u" format that will parse the next argument
73 passed to the
74 .Xr xo_emit 3 ,
75 function as an unsigned integer.
76 .Bd -literal -offset indent
77     xo_emit("{P:   }{Lwc:In stock}{:in-stock/%u}\\n", 65);
78 .Ed
79 .Pp
80 This single line of code can generate text ("In stock: 65\\n"), XML
81 ("<in-stock>65</in-stock>"), JSON ('"in-stock": 65'), or HTML (too
82 lengthy to be listed here).
83 .Pp
84 While roles and modifiers typically use single character for brevity,
85 there are alternative names for each which allow more verbose
86 formatting strings.
87 These names must be preceded by a comma, and may follow any
88 single-character values:
89 .Bd -literal -offset indent
90     xo_emit("{L,white,colon:In stock}{,key:in-stock/%u}\n", 65);
91 .Ed
92 .Ss "Field Roles"
93 Field roles are optional, and indicate the role and formatting of the
94 content.
95 The roles are listed below; only one role is permitted:
96 .Bl -column "M" "Name12341234"
97 .It Sy "M" "Name        " "Description"
98 .It C "color       " "Field is a color or effect"
99 .It D "decoration  " "Field is non-text (e.g. colon, comma)"
100 .It E "error       " "Field is an error message"
101 .It L "label       " "Field is text that prefixes a value"
102 .It N "note        " "Field is text that follows a value"
103 .It P "padding     " "Field is spaces needed for vertical alignment"
104 .It T "title       " "Field is a title value for headings"
105 .It U "units       " "Field is the units for the previous value field"
106 .It V "value       " "Field is the name of field (the default)"
107 .It W "warning     " "Field is a warning message"
108 .It \&[ "start-anchor" "Begin a section of anchored variable-width text"
109 .It \&] "stop-anchor " "End a section of anchored variable-width text"
110 .El
111 .Bd -literal -offset indent
112    EXAMPLE:
113        xo_emit("{L:Free}{D::}{P:   }{:free/%u} {U:Blocks}\n",
114                free_blocks);
115 .Ed
116 .Pp
117 When a role is not provided, the "value" role is used as the default.
118 .Pp
119 Roles and modifiers can also use more verbose names, when preceeded by
120 a comma:
121 .Bd -literal -offset indent
122    EXAMPLE:
123         xo_emit("{,label:Free}{,decoration::}{,padding:   }"
124                "{,value:free/%u} {,units:Blocks}\n",
125                free_blocks);
126 .Ed
127 .Ss "The Color Role ({C:})"
128 Colors and effects control how text values are displayed; they are
129 used for display styles (TEXT and HTML).
130 .Bd -literal -offset indent
131     xo_emit("{C:bold}{:value}{C:no-bold}\n", value);
132 .Ed
133 .Pp
134 Colors and effects remain in effect until modified by other "C"-role
135 fields.
136 .Bd -literal -offset indent
137     xo_emit("{C:bold}{C:inverse}both{C:no-bold}only inverse\n");
138 .Ed
139 .Pp
140 If the content is empty, the "reset" action is performed.
141 .Bd -literal -offset indent
142     xo_emit("{C:both,underline}{:value}{C:}\n", value);
143 .Ed
144 .Pp
145 The content should be a comma-separated list of zero or more colors or
146 display effects.
147 .Bd -literal -offset indent
148     xo_emit("{C:bold,underline,inverse}All three{C:no-bold,no-inverse}\n");
149 .Ed
150 .Pp
151 The color content can be either static, when placed directly within
152 the field descriptor, or a printf-style format descriptor can be used,
153 if preceded by a slash ("/"):
154 .Bd -literal -offset indent
155    xo_emit("{C:/%s%s}{:value}{C:}", need_bold ? "bold" : "",
156            need_underline ? "underline" : "", value);
157 .Ed
158 .Pp
159 Color names are prefixed with either "fg-" or "bg-" to change the
160 foreground and background colors, respectively.
161 .Bd -literal -offset indent
162     xo_emit("{C:/fg-%s,bg-%s}{Lwc:Cost}{:cost/%u}{C:reset}\n",
163             fg_color, bg_color, cost);
164 .Ed
165 .Pp
166 The following table lists the supported effects:
167 .Bl -column "no-underline"
168 .It Sy "Name         " "Description"
169 .It "bg\-xxxxx     " "Change background color"
170 .It "bold         " "Start bold text effect"
171 .It "fg\-xxxxx     " "Change foreground color"
172 .It "inverse      " "Start inverse (aka reverse) text effect"
173 .It "no\-bold      " "Stop bold text effect"
174 .It "no\-inverse   " "Stop inverse (aka reverse) text effect"
175 .It "no\-underline " "Stop underline text effect"
176 .It "normal       " "Reset effects (only)"
177 .It "reset        " "Reset colors and effects (restore defaults)"
178 .It "underline    " "Start underline text effect"
179 .El
180 .Pp
181 The following color names are supported:
182 .Bl -column "no-underline"
183 .It Sy "Name"
184 .It black
185 .It blue
186 .It cyan
187 .It default
188 .It green
189 .It magenta
190 .It red
191 .It white
192 .It yellow
193 .El
194 .Ss "The Decoration Role ({D:})"
195 Decorations are typically punctuation marks such as colons,
196 semi-colons, and commas used to decorate the text and make it simpler
197 for human readers.
198 By marking these distinctly, HTML usage scenarios
199 can use CSS to direct their display parameters.
200 .Bd -literal -offset indent
201     xo_emit("{D:((}{:name}{D:))}\\n", name);
202 .Ed
203 .Ss "The Gettext Role ({G:})"
204 .Nm libxo
205 supports internationalization (i18n) through its use of
206 .Xr gettext 3 .
207 Use the "{G:}" role to request that the remaining part of
208 the format string, following the "{G:}" field, be handled using
209 .Fn gettext .
210 Since
211 .Fn gettext
212 uses the string as the key into the message catalog,
213 .Nm libxo
214 uses a simplified version of the format string that removes
215 unimportant field formatting and modifiers, stopping minor formatting
216 changes from impacting the expensive translation process.
217 A developer
218 change such as changing "/%06d" to "/%08d" should not force hand
219 inspection of all .po files.
220 .Pp
221 The simplified version can be generated for a single message using the
222 "xopo -s <text>" command, or an entire .pot can be translated using
223 the "xopo -f <input> -o <output>" command.
224 .Bd -literal -offset indent
225    xo_emit("{G:}Invalid token\n");
226 .Ed
227 The {G:} role allows a domain name to be set.
228 .Fn gettext
229 calls will
230 continue to use that domain name until the current format string
231 processing is complete, enabling a library function to emit strings
232 using it's own catalog.
233 The domain name can be either static as the
234 content of the field, or a format can be used to get the domain name
235 from the arguments.
236 .Bd -literal -offset indent
237    xo_emit("{G:libc}Service unavailable in restricted mode\n");
238 .Ed
239 .Ss "The Label Role ({L:})"
240 Labels are text that appears before a value.
241 .Bd -literal -offset indent
242     xo_emit("{Lwc:Cost}{:cost/%u}\\n", cost);
243 .Ed
244 .Ss "The Note Role ({N:})"
245 Notes are text that appears after a value.
246 .Bd -literal -offset indent
247     xo_emit("{:cost/%u} {N:per year}\\n", cost);
248 .Ed
249 .Ss "The Padding Role ({P:})"
250 Padding represents whitespace used before and between fields.
251 The padding content can be either static, when placed directly within
252 the field descriptor, or a printf-style format descriptor can be used,
253 if preceded by a slash ("/"):
254 .Bd -literal -offset indent
255     xo_emit("{P:        }{Lwc:Cost}{:cost/%u}\\n", cost);
256     xo_emit("{P:/30s}{Lwc:Cost}{:cost/%u}\\n", "", cost);
257 .Ed
258 .Ss "The Title Role ({T:})"
259 Titles are heading or column headers that are meant to be displayed to
260 the user.
261 The title can be either static, when placed directly within
262 the field descriptor, or a printf-style format descriptor can be used,
263 if preceded by a slash ("/"):
264 .Bd -literal -offset indent
265     xo_emit("{T:Interface Statistics}\\n");
266     xo_emit("{T:/%20.20s}{T:/%6.6s}\\n", "Item Name", "Cost");
267 .Ed
268 .Ss "The Units Role ({U:})"
269 Units are the dimension by which values are measured, such as degrees,
270 miles, bytes, and decibels.
271 The units field carries this information
272 for the previous value field.
273 .Bd -literal -offset indent
274     xo_emit("{Lwc:Distance}{:distance/%u}{Uw:miles}\\n", miles);
275 .Ed
276 .Pp
277 Note that the sense of the 'w' modifier is reversed for units;
278 a blank is added before the contents, rather than after it.
279 .Pp
280 When the
281 .Dv XOF_UNITS
282 flag is set, units are rendered in XML as the
283 .Dq units
284 attribute:
285 .Bd -literal -offset indent
286     <distance units="miles">50</distance>
287 .Ed
288 .Pp
289 Units can also be rendered in HTML as the "data-units" attribute:
290 .Bd -literal -offset indent
291     <div class="data" data-tag="distance" data-units="miles"
292          data-xpath="/top/data/distance">50</div>
293 .Ed
294 .Ss "The Value Role ({V:} and {:})"
295 The value role is used to represent the a data value that is
296 interesting for the non-display output styles (XML and JSON).
297 Value
298 is the default role; if no other role designation is given, the field
299 is a value.
300 The field name must appear within the field descriptor,
301 followed by one or two format descriptors.
302 The first format
303 descriptor is used for display styles (TEXT and HTML), while the
304 second one is used for encoding styles (XML and JSON).
305 If no second
306 format is given, the encoding format defaults to the first format,
307 with any minimum width removed.
308 If no first format is given, both
309 format descriptors default to "%s".
310 .Bd -literal -offset indent
311     xo_emit("{:length/%02u}x{:width/%02u}x{:height/%02u}\\n",
312             length, width, height);
313     xo_emit("{:author} wrote \"{:poem}\" in {:year/%4d}\\n,
314             author, poem, year);
315 .Ed
316 .Ss "The Anchor Roles ({[:} and {]:})"
317 The anchor roles allow a set of strings by be padded as a group,
318 but still be visible to
319 .Xr xo_emit 3
320 as distinct fields.
321 Either the start
322 or stop anchor can give a field width and it can be either directly in
323 the descriptor or passed as an argument.
324 Any fields between the start
325 and stop anchor are padded to meet the minimum width given.
326 .Pp
327 To give a width directly, encode it as the content of the anchor tag:
328 .Bd -literal -offset indent
329     xo_emit("({[:10}{:min/%d}/{:max/%d}{]:})\\n", min, max);
330 .Ed
331 .Pp
332 To pass a width as an argument, use "%d" as the format, which must
333 appear after the "/".
334 Note that only "%d" is supported for widths.
335 Using any other value could ruin your day.
336 .Bd -literal -offset indent
337     xo_emit("({[:/%d}{:min/%d}/{:max/%d}{]:})\\n", width, min, max);
338 .Ed
339 .Pp
340 If the width is negative, padding will be added on the right, suitable
341 for left justification.
342 Otherwise the padding will be added to the
343 left of the fields between the start and stop anchors, suitable for
344 right justification.
345 If the width is zero, nothing happens.
346 If the
347 number of columns of output between the start and stop anchors is less
348 than the absolute value of the given width, nothing happens.
349 .Pp
350 Widths over 8k are considered probable errors and not supported.
351 If
352 .Dv XOF_WARN
353 is set, a warning will be generated.
354 .Ss "Field Modifiers"
355 Field modifiers are flags which modify the way content emitted for
356 particular output styles:
357 .Bl -column M "Name123456789"
358 .It Sy M "Name          " "Description"
359 .It c "colon         " "A colon ("":"") is appended after the label"
360 .It d "display       " "Only emit field for display styles (text/HTML)"
361 .It e "encoding      " "Only emit for encoding styles (XML/JSON)"
362 .It h "humanize (hn) " "Format large numbers in human-readable style"
363 .It " " "hn-space     " "Humanize: Place space between numeric and unit"
364 .It " " "hn-decimal   " "Humanize: Add a decimal digit, if number < 10"
365 .It " " "hn-1000      " "Humanize: Use 1000 as divisor instead of 1024"
366 .It k "key           " "Field is a key, suitable for XPath predicates"
367 .It l "leaf-list    " "Field is a leaf-list, a list of leaf values"
368 .It n "no-quotes    " "Do not quote the field when using JSON style"
369 .It q "quotes        " "Quote the field when using JSON style"
370 .It q "trim          " "Trim leading and trailing whitespace"
371 .It w "white space   " "A blank ("" "") is appended after the label"
372 .El
373 .Pp
374 For example, the modifier string "Lwc" means the field has a label
375 role (text that describes the next field) and should be followed by a
376 colon ('c') and a space ('w').
377 The modifier string "Vkq" means the
378 field has a value role, that it is a key for the current instance, and
379 that the value should be quoted when encoded for JSON.
380 .Pp
381 Roles and modifiers can also use more verbose names, when preceeded by
382 a comma.
383 For example, the modifier string "Lwc" (or "L,white,colon")
384 means the field has a label role (text that describes the next field)
385 and should be followed by a colon ('c') and a space ('w').
386 The modifier string "Vkq" (or ":key,quote") means the field has a value
387 role (the default role), that it is a key for the current instance,
388 and that the value should be quoted when encoded for JSON.
389 .Ss "The Colon Modifier ({c:})"
390 The colon modifier appends a single colon to the data value:
391 .Bd -literal -offset indent
392     EXAMPLE:
393       xo_emit("{Lc:Name}{:name}\\n", "phil");
394     TEXT:
395       Name:phil
396 .Ed
397 .Pp
398 The colon modifier is only used for the TEXT and HTML output
399 styles.
400 It is commonly combined with the space modifier ('{w:}').
401 It is purely a convenience feature.
402 .Ss "The Display Modifier ({d:})"
403 The display modifier indicated the field should only be generated for
404 the display output styles, TEXT and HTML.
405 .Bd -literal -offset indent
406     EXAMPLE:
407       xo_emit("{Lcw:Name}{d:name} {:id/%d}\\n", "phil", 1);
408     TEXT:
409       Name: phil 1
410     XML:
411       <id>1</id>
412 .Ed
413 .Pp
414 The display modifier is the opposite of the encoding modifier, and
415 they are often used to give to distinct views of the underlying data.
416 .Ss "The Encoding Modifier ({e:})"
417 The encoding modifier indicated the field should only be generated for
418 the encoding output styles, such as JSON and XML.
419 .Bd -literal -offset indent
420     EXAMPLE:
421       xo_emit("{Lcw:Name}{:name} {e:id/%d}\\n", "phil", 1);
422     TEXT:
423       Name: phil
424     XML:
425       <name>phil</name><id>1</id>
426 .Ed
427 .Pp
428 The encoding modifier is the opposite of the display modifier, and
429 they are often used to give to distinct views of the underlying data.
430 .Ss "The Humanize Modifier ({h:})"
431 The humanize modifier is used to render large numbers as in a
432 human-readable format.
433 While numbers like "44470272" are completely readable to computers and
434 savants, humans will generally find "44M" more meaningful.
435 .Pp
436 "hn" can be used as an alias for "humanize".
437 .Pp
438 The humanize modifier only affects display styles (TEXT and HMTL).
439 The "no-humanize" option will block the function of the humanize modifier.
440 .Pp
441 There are a number of modifiers that affect details of humanization.
442 These are only available in as full names, not single characters.
443 The "hn-space" modifier places a space between the number and any
444 multiplier symbol, such as "M" or "K" (ex: "44 K").
445 The "hn-decimal" modifier will add a decimal point and a single tenths digit
446 when the number is less than 10 (ex: "4.4K").
447 The "hn-1000" modifier will use 1000 as divisor instead of 1024, following the
448 JEDEC-standard instead of the more natural binary powers-of-two
449 tradition.
450 .Bd -literal -offset indent
451     EXAMPLE:
452         xo_emit("{h:input/%u}, {h,hn-space:output/%u}, "
453            "{h,hn-decimal:errors/%u}, {h,hn-1000:capacity/%u}, "
454            "{h,hn-decimal:remaining/%u}\n",
455             input, output, errors, capacity, remaining);
456     TEXT:
457         21, 57 K, 96M, 44M, 1.2G
458 .Ed
459 .Pp
460 In the HTML style, the original numeric value is rendered in the
461 "data-number" attribute on the <div> element:
462 .Bd -literal -offset indent
463     <div class="data" data-tag="errors"
464          data-number="100663296">96M</div>
465 .Ed
466 .Ss "The Gettext Modifier ({g:})"
467 The gettext modifier is used to translate individual fields using the
468 gettext domain (typically set using the "{G:}" role) and current
469 language settings.
470 Once libxo renders the field value, it is passed
471 to
472 .Xr gettext 3 ,
473 where it is used as a key to find the native language
474 translation.
475 .Pp
476 In the following example, the strings "State" and "full" are passed
477 to
478 .Fn gettext
479 to find locale-based translated strings.
480 .Bd -literal -offset indent
481     xo_emit("{Lgwc:State}{g:state}\n", "full");
482 .Ed
483 .Ss "The Key Modifier ({k:})"
484 The key modifier is used to indicate that a particular field helps
485 uniquely identify an instance of list data.
486 .Bd -literal -offset indent
487     EXAMPLE:
488         xo_open_list("user");
489         for (i = 0; i < num_users; i++) {
490             xo_open_instance("user");
491             xo_emit("User {k:name} has {:count} tickets\\n",
492                user[i].u_name, user[i].u_tickets);
493             xo_close_instance("user");
494         }
495         xo_close_list("user");
496 .Ed
497 .Pp
498 Currently the key modifier is only used when generating XPath values
499 for the HTML output style when
500 .Dv XOF_XPATH
501 is set, but other uses are likely in the near future.
502 .Ss "The Leaf-List Modifier ({l:})"
503 The leaf-list modifier is used to distinguish lists where each
504 instance consists of only a single value.  In XML, these are
505 rendered as single elements, where JSON renders them as arrays.
506 .Bd -literal -offset indent
507     EXAMPLE:
508         xo_open_list("user");
509         for (i = 0; i < num_users; i++) {
510             xo_emit("Member {l:name}\n", user[i].u_name);
511         }
512         xo_close_list("user");
513     XML:
514         <user>phil</user>
515         <user>pallavi</user>
516     JSON:
517         "user": [ "phil", "pallavi" ]
518 .Ed
519 .Ss "The No-Quotes Modifier ({n:})"
520 The no-quotes modifier (and its twin, the 'quotes' modifier) affect
521 the quoting of values in the JSON output style.
522 JSON uses quotes for
523 string values, but no quotes for numeric, boolean, and null data.
524 .Xr xo_emit 3
525 applies a simple heuristic to determine whether quotes are
526 needed, but often this needs to be controlled by the caller.
527 .Bd -literal -offset indent
528     EXAMPLE:
529       const char *bool = is_true ? "true" : "false";
530       xo_emit("{n:fancy/%s}", bool);
531     JSON:
532       "fancy": true
533 .Ed
534 .Ss "The Plural Modifier ({p:})"
535 The plural modifier selects the appropriate plural form of an
536 expression based on the most recent number emitted and the current
537 language settings.
538 The contents of the field should be the singular
539 and plural English values, separated by a comma:
540 .Bd -literal -offset indent
541     xo_emit("{:bytes} {Ngp:byte,bytes}\n", bytes);
542 .Ed
543 The plural modifier is meant to work with the gettext modifier ({g:})
544 but can work independently.
545 .Pp
546 When used without the gettext modifier or when the message does not
547 appear in the message catalog, the first token is chosen when the last
548 numeric value is equal to 1; otherwise the second value is used,
549 mimicking the simple pluralization rules of English.
550 .Pp
551 When used with the gettext modifier, the
552 .Xr ngettext 3
553 function is
554 called to handle the heavy lifting, using the message catalog to
555 convert the singular and plural forms into the native language.
556 .Ss "The Quotes Modifier ({q:})"
557 The quotes modifier (and its twin, the 'no-quotes' modifier) affect
558 the quoting of values in the JSON output style.
559 JSON uses quotes for
560 string values, but no quotes for numeric, boolean, and null data.
561 .Xr xo_emit 3
562 applies a simple heuristic to determine whether quotes are
563 needed, but often this needs to be controlled by the caller.
564 .Bd -literal -offset indent
565     EXAMPLE:
566       xo_emit("{q:time/%d}", 2014);
567     JSON:
568       "year": "2014"
569 .Ed
570 .Ss "The White Space Modifier ({w:})"
571 The white space modifier appends a single space to the data value:
572 .Bd -literal -offset indent
573     EXAMPLE:
574       xo_emit("{Lw:Name}{:name}\\n", "phil");
575     TEXT:
576       Name phil
577 .Ed
578 .Pp
579 The white space modifier is only used for the TEXT and HTML output
580 styles.
581 It is commonly combined with the colon modifier ('{c:}').
582 It is purely a convenience feature.
583 .Pp
584 Note that the sense of the 'w' modifier is reversed for the units role
585 ({Uw:}); a blank is added before the contents, rather than after it.
586 .Ss "Field Formatting"
587 The field format is similar to the format string for
588 .Xr printf 3 .
589 Its use varies based on the role of the field, but generally is used to
590 format the field's contents.
591 .Pp
592 If the format string is not provided for a value field, it defaults
593 to "%s".
594 .Pp
595 Note a field definition can contain zero or more printf-style
596 .Dq directives ,
597 which are sequences that start with a '%' and end with
598 one of following characters: "diouxXDOUeEfFgGaAcCsSp".
599 Each directive
600 is matched by one of more arguments to the
601 .Xr xo_emit 3
602 function.
603 .Pp
604 The format string has the form:
605 .Bd -literal -offset indent
606   '%' format-modifier * format-character
607 .Ed
608 .Pp
609 The format- modifier can be:
610 .Bl -bullet
611 .It
612 a '#' character, indicating the output value should be prefixed with
613 "0x", typically to indicate a base 16 (hex) value.
614 .It
615 a minus sign ('-'), indicating the output value should be padded on
616 the right instead of the left.
617 .It
618 a leading zero ('0') indicating the output value should be padded on the
619 left with zeroes instead of spaces (' ').
620 .It
621 one or more digits ('0' - '9') indicating the minimum width of the
622 argument.
623 If the width in columns of the output value is less than
624 the minimum width, the value will be padded to reach the minimum.
625 .It
626 a period followed by one or more digits indicating the maximum
627 number of bytes which will be examined for a string argument, or the maximum
628 width for a non-string argument.
629 When handling ASCII strings this
630 functions as the field width but for multi-byte characters, a single
631 character may be composed of multiple bytes.
632 .Xr xo_emit 3
633 will never dereference memory beyond the given number of bytes.
634 .It
635 a second period followed by one or more digits indicating the maximum
636 width for a string argument.
637 This modifier cannot be given for non-string arguments.
638 .It
639 one or more 'h' characters, indicating shorter input data.
640 .It
641 one or more 'l' characters, indicating longer input data.
642 .It
643 a 'z' character, indicating a 'size_t' argument.
644 .It
645 a 't' character, indicating a 'ptrdiff_t' argument.
646 .It
647 a ' ' character, indicating a space should be emitted before
648 positive numbers.
649 .It
650 a '+' character, indicating sign should emitted before any number.
651 .El
652 .Pp
653 Note that 'q', 'D', 'O', and 'U' are considered deprecated and will be
654 removed eventually.
655 .Pp
656 The format character is described in the following table:
657 .Bl -column C "Argument Type12"
658 .It Sy "C" "Argument Type  " "Format"
659 .It d "int            " "base 10 (decimal)"
660 .It i "int            " "base 10 (decimal)"
661 .It o "int            " "base 8 (octal)"
662 .It u "unsigned       " "base 10 (decimal)"
663 .It x "unsigned       " "base 16 (hex)"
664 .It X "unsigned long  " "base 16 (hex)"
665 .It D "long           " "base 10 (decimal)"
666 .It O "unsigned long  " "base 8 (octal)"
667 .It U "unsigned long  " "base 10 (decimal)"
668 .It e "double         " "[-]d.ddde+-dd"
669 .It E "double         " "[-]d.dddE+-dd"
670 .It f "double         " "[-]ddd.ddd"
671 .It F "double         " "[-]ddd.ddd"
672 .It g "double         " "as 'e' or 'f'"
673 .It G "double         " "as 'E' or 'F'"
674 .It a "double         " "[-]0xh.hhhp[+-]d"
675 .It A "double         " "[-]0Xh.hhhp[+-]d"
676 .It c "unsigned char  " "a character"
677 .It C "wint_t         " "a character"
678 .It s "char *         " "a UTF-8 string"
679 .It S "wchar_t *      " "a unicode/WCS string"
680 .It p "void *         " "'%#lx'"
681 .El
682 .Pp
683 The 'h' and 'l' modifiers affect the size and treatment of the
684 argument:
685 .Bl -column "Mod" "d, i         " "o, u, x, X         "
686 .It Sy "Mod" "d, i        " "o, u, x, X"
687 .It "hh " "signed char " "unsigned char"
688 .It "h  " "short       " "unsigned short"
689 .It "l  " "long        " "unsigned long"
690 .It "ll " "long long   " "unsigned long long"
691 .It "j  " "intmax_t    " "uintmax_t"
692 .It "t  " "ptrdiff_t   " "ptrdiff_t"
693 .It "z  " "size_t      " "size_t"
694 .It "q  " "quad_t      " "u_quad_t"
695 .El
696 .Ss "UTF-8 and Locale Strings"
697 All strings for
698 .Nm libxo
699 must be UTF-8.
700 .Nm libxo
701 will handle turning them
702 into locale-based strings for display to the user.
703 .Pp
704 For strings, the 'h' and 'l' modifiers affect the interpretation of
705 the bytes pointed to argument.
706 The default '%s' string is a 'char *'
707 pointer to a string encoded as UTF-8.
708 Since UTF-8 is compatible with
709 .Em ASCII
710 data, a normal 7-bit
711 .Em ASCII
712 string can be used.
713 "%ls" expects a
714 "wchar_t *" pointer to a wide-character string, encoded as 32-bit
715 Unicode values.
716 "%hs" expects a "char *" pointer to a multi-byte
717 string encoded with the current locale, as given by the
718 .Ev LC_CTYPE ,
719 .Ev LANG ,
720 or
721 .Ev LC_ALL
722 environment variables.
723 The first of this list of
724 variables is used and if none of the variables are set, the locale defaults to
725 .Em UTF-8 .
726 .Pp
727 .Nm libxo
728 will
729 convert these arguments as needed to either UTF-8 (for XML, JSON, and
730 HTML styles) or locale-based strings for display in text style.
731 .Bd -literal -offset indent
732    xo_emit("All strings are utf-8 content {:tag/%ls}",
733            L"except for wide strings");
734 .Ed
735 .Pp
736 "%S" is equivalent to "%ls".
737 .Pp
738 For example, a function is passed a locale-base name, a hat size,
739 and a time value.
740 The hat size is formatted in a UTF-8 (ASCII)
741 string, and the time value is formatted into a wchar_t string.
742 .Bd -literal -offset indent
743     void print_order (const char *name, int size,
744                       struct tm *timep) {
745         char buf[32];
746         const char *size_val = "unknown";
747
748         if (size > 0)
749             snprintf(buf, sizeof(buf), "%d", size);
750             size_val = buf;
751         }
752
753         wchar_t when[32];
754         wcsftime(when, sizeof(when), L"%d%b%y", timep);
755
756         xo_emit("The hat for {:name/%hs} is {:size/%s}.\\n",
757                 name, size_val);
758         xo_emit("It was ordered on {:order-time/%ls}.\\n",
759                 when);
760     }
761 .Ed
762 .Pp
763 It is important to note that
764 .Xr xo_emit 3
765 will perform the conversion
766 required to make appropriate output.
767 Text style output uses the
768 current locale (as described above), while XML, JSON, and HTML use
769 UTF-8.
770 .Pp
771 UTF-8 and locale-encoded strings can use multiple bytes to encode one
772 column of data.
773 The traditional "precision'" (aka "max-width") value
774 for "%s" printf formatting becomes overloaded since it specifies both
775 the number of bytes that can be safely referenced and the maximum
776 number of columns to emit.
777 .Xr xo_emit 3
778 uses the precision as the former,
779 and adds a third value for specifying the maximum number of columns.
780 .Pp
781 In this example, the name field is printed with a minimum of 3 columns
782 and a maximum of 6.
783 Up to ten bytes are in used in filling those columns.
784 .Bd -literal -offset indent
785     xo_emit("{:name/%3.10.6s}", name);
786 .Ed
787 .Ss "Characters Outside of Field Definitions"
788 Characters in the format string that are not part of a field definition are
789 copied to the output for the TEXT style, and are ignored for the JSON
790 and XML styles.
791 For HTML, these characters are placed in a <div> with class "text".
792 .Bd -literal -offset indent
793   EXAMPLE:
794       xo_emit("The hat is {:size/%s}.\\n", size_val);
795   TEXT:
796       The hat is extra small.
797   XML:
798       <size>extra small</size>
799   JSON:
800       "size": "extra small"
801   HTML:
802       <div class="text">The hat is </div>
803       <div class="data" data-tag="size">extra small</div>
804       <div class="text">.</div>
805 .Ed
806 .Ss "'%n' is Not Supported"
807 .Nm libxo
808 does not support the '%n' directive.
809 It is a bad idea and we
810 just do not do it.
811 .Ss "The Encoding Format (eformat)"
812 The "eformat" string is the format string used when encoding the field
813 for JSON and XML.
814 If not provided, it defaults to the primary format
815 with any minimum width removed.
816 If the primary is not given, both default to "%s".
817 .Sh EXAMPLE
818 In this example, the value for the number of items in stock is emitted:
819 .Bd -literal -offset indent
820         xo_emit("{P:   }{Lwc:In stock}{:in-stock/%u}\\n",
821                 instock);
822 .Ed
823 .Pp
824 This call will generate the following output:
825 .Bd -literal -offset indent
826   TEXT:
827        In stock: 144
828   XML:
829       <in-stock>144</in-stock>
830   JSON:
831       "in-stock": 144,
832   HTML:
833       <div class="line">
834         <div class="padding">   </div>
835         <div class="label">In stock</div>
836         <div class="decoration">:</div>
837         <div class="padding"> </div>
838         <div class="data" data-tag="in-stock">144</div>
839       </div>
840 .Ed
841 .Pp
842 Clearly HTML wins the verbosity award, and this output does
843 not include
844 .Dv XOF_XPATH
845 or
846 .Dv XOF_INFO
847 data, which would expand the penultimate line to:
848 .Bd -literal -offset indent
849        <div class="data" data-tag="in-stock"
850           data-xpath="/top/data/item/in-stock"
851           data-type="number"
852           data-help="Number of items in stock">144</div>
853 .Ed
854 .Sh WHAT MAKES A GOOD FIELD NAME?
855 To make useful, consistent field names, follow these guidelines:
856 .Ss "Use lower case, even for TLAs"
857 Lower case is more civilized.
858 Even TLAs should be lower case
859 to avoid scenarios where the differences between "XPath" and
860 "Xpath" drive your users crazy.
861 Using "xpath" is simpler and better.
862 .Ss "Use hyphens, not underscores"
863 Use of hyphens is traditional in XML, and the
864 .Dv XOF_UNDERSCORES
865 flag can be used to generate underscores in JSON, if desired.
866 But the raw field name should use hyphens.
867 .Ss "Use full words"
868 Do not abbreviate especially when the abbreviation is not obvious or
869 not widely used.
870 Use "data-size", not "dsz" or "dsize".
871 Use
872 "interface" instead of "ifname", "if-name", "iface", "if", or "intf".
873 .Ss "Use <verb>-<units>"
874 Using the form <verb>-<units> or <verb>-<classifier>-<units> helps in
875 making consistent, useful names, avoiding the situation where one app
876 uses "sent-packet" and another "packets-sent" and another
877 "packets-we-have-sent".
878 The <units> can be dropped when it is
879 obvious, as can obvious words in the classification.
880 Use "receive-after-window-packets" instead of
881 "received-packets-of-data-after-window".
882 .Ss "Reuse existing field names"
883 Nothing is worse than writing expressions like:
884 .Bd -literal -offset indent
885     if ($src1/process[pid == $pid]/name ==
886         $src2/proc-table/proc/p[process-id == $pid]/proc-name) {
887         ...
888     }
889 .Ed
890 .Pp
891 Find someone else who is expressing similar data and follow their
892 fields and hierarchy.
893 Remember the quote is not
894 .Dq "Consistency is the hobgoblin of little minds"
895 but
896 .Dq "A foolish consistency is the hobgoblin of little minds" .
897 .Ss "Think about your users"
898 Have empathy for your users, choosing clear and useful fields that
899 contain clear and useful data.
900 You may need to augment the display content with
901 .Xr xo_attr 3
902 calls or "{e:}" fields to make the data useful.
903 .Ss "Do not use an arbitrary number postfix"
904 What does "errors2" mean?
905 No one will know.
906 "errors-after-restart" would be a better choice.
907 Think of your users, and think of the future.
908 If you make "errors2", the next guy will happily make
909 "errors3" and before you know it, someone will be asking what is the
910 difference between errors37 and errors63.
911 .Ss "Be consistent, uniform, unsurprising, and predictable"
912 Think of your field vocabulary as an API.
913 You want it useful,
914 expressive, meaningful, direct, and obvious.
915 You want the client
916 application's programmer to move between without the need to
917 understand a variety of opinions on how fields are named.
918 They should
919 see the system as a single cohesive whole, not a sack of cats.
920 .Pp
921 Field names constitute the means by which client programmers interact
922 with our system.
923 By choosing wise names now, you are making their lives better.
924 .Pp
925 After using
926 .Xr xolint 1
927 to find errors in your field descriptors, use
928 .Dq "xolint -V"
929 to spell check your field names and to detect different
930 names for the same data.
931 .Dq dropped-short
932 and
933 .Dq dropped-too-short
934 are both reasonable names, but using them both will lead users to ask the
935 difference between the two fields.
936 If there is no difference,
937 use only one of the field names.
938 If there is a difference, change the
939 names to make that difference more obvious.
940 .Sh SEE ALSO
941 .Xr libxo 3 ,
942 .Xr xolint 1 ,
943 .Xr xo_emit 3