]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/libxo/libxo/xo_format.5
Import to 0.6.1
[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 November 6, 2015
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     \(aq{\(aq [ role | modifier ]* [\(aq,\(aq long\-names ]* \(aq:\(aq [ content ]
55             [ \(aq/\(aq field\-format [ \(aq/\(aq encoding\-format ]] \(aq}\(aq
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 (\(aq"in\-stock": 65\(aq), 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 .Pp
228 The {G:} role allows a domain name to be set.
229 .Fn gettext
230 calls will
231 continue to use that domain name until the current format string
232 processing is complete, enabling a library function to emit strings
233 using it\(aqs own catalog.
234 The domain name can be either static as the
235 content of the field, or a format can be used to get the domain name
236 from the arguments.
237 .Bd -literal -offset indent
238    xo_emit("{G:libc}Service unavailable in restricted mode\\n");
239 .Ed
240 .Ss "The Label Role ({L:})"
241 Labels are text that appears before a value.
242 .Bd -literal -offset indent
243     xo_emit("{Lwc:Cost}{:cost/%u}\\n", cost);
244 .Ed
245 .Ss "The Note Role ({N:})"
246 Notes are text that appears after a value.
247 .Bd -literal -offset indent
248     xo_emit("{:cost/%u} {N:per year}\\n", cost);
249 .Ed
250 .Ss "The Padding Role ({P:})"
251 Padding represents whitespace used before and between fields.
252 The padding content can be either static, when placed directly within
253 the field descriptor, or a printf\-style format descriptor can be used,
254 if preceded by a slash ("/"):
255 .Bd -literal -offset indent
256     xo_emit("{P:        }{Lwc:Cost}{:cost/%u}\\n", cost);
257     xo_emit("{P:/30s}{Lwc:Cost}{:cost/%u}\\n", "", cost);
258 .Ed
259 .Ss "The Title Role ({T:})"
260 Titles are heading or column headers that are meant to be displayed to
261 the user.
262 The title can be either static, when placed directly within
263 the field descriptor, or a printf\-style format descriptor can be used,
264 if preceded by a slash ("/"):
265 .Bd -literal -offset indent
266     xo_emit("{T:Interface Statistics}\\n");
267     xo_emit("{T:/%20.20s}{T:/%6.6s}\\n", "Item Name", "Cost");
268 .Ed
269 .Ss "The Units Role ({U:})"
270 Units are the dimension by which values are measured, such as degrees,
271 miles, bytes, and decibels.
272 The units field carries this information
273 for the previous value field.
274 .Bd -literal -offset indent
275     xo_emit("{Lwc:Distance}{:distance/%u}{Uw:miles}\\n", miles);
276 .Ed
277 .Pp
278 Note that the sense of the \(aqw\(aq modifier is reversed for units;
279 a blank is added before the contents, rather than after it.
280 .Pp
281 When the
282 .Dv XOF_UNITS
283 flag is set, units are rendered in XML as the
284 .Dq units
285 attribute:
286 .Bd -literal -offset indent
287     <distance units="miles">50</distance>
288 .Ed
289 .Pp
290 Units can also be rendered in HTML as the "data\-units" attribute:
291 .Bd -literal -offset indent
292     <div class="data" data\-tag="distance" data\-units="miles"
293          data\-xpath="/top/data/distance">50</div>
294 .Ed
295 .Ss "The Value Role ({V:} and {:})"
296 The value role is used to represent the a data value that is
297 interesting for the non\-display output styles (XML and JSON).
298 Value
299 is the default role; if no other role designation is given, the field
300 is a value.
301 The field name must appear within the field descriptor,
302 followed by one or two format descriptors.
303 The first format
304 descriptor is used for display styles (TEXT and HTML), while the
305 second one is used for encoding styles (XML and JSON).
306 If no second
307 format is given, the encoding format defaults to the first format,
308 with any minimum width removed.
309 If no first format is given, both
310 format descriptors default to "%s".
311 .Bd -literal -offset indent
312     xo_emit("{:length/%02u}x{:width/%02u}x{:height/%02u}\\n",
313             length, width, height);
314     xo_emit("{:author} wrote \"{:poem}\" in {:year/%4d}\\n,
315             author, poem, year);
316 .Ed
317 .Ss "The Anchor Roles ({[:} and {]:})"
318 The anchor roles allow a set of strings by be padded as a group,
319 but still be visible to
320 .Xr xo_emit 3
321 as distinct fields.
322 Either the start
323 or stop anchor can give a field width and it can be either directly in
324 the descriptor or passed as an argument.
325 Any fields between the start
326 and stop anchor are padded to meet the minimum width given.
327 .Pp
328 To give a width directly, encode it as the content of the anchor tag:
329 .Bd -literal -offset indent
330     xo_emit("({[:10}{:min/%d}/{:max/%d}{]:})\\n", min, max);
331 .Ed
332 .Pp
333 To pass a width as an argument, use "%d" as the format, which must
334 appear after the "/".
335 Note that only "%d" is supported for widths.
336 Using any other value could ruin your day.
337 .Bd -literal -offset indent
338     xo_emit("({[:/%d}{:min/%d}/{:max/%d}{]:})\\n", width, min, max);
339 .Ed
340 .Pp
341 If the width is negative, padding will be added on the right, suitable
342 for left justification.
343 Otherwise the padding will be added to the
344 left of the fields between the start and stop anchors, suitable for
345 right justification.
346 If the width is zero, nothing happens.
347 If the
348 number of columns of output between the start and stop anchors is less
349 than the absolute value of the given width, nothing happens.
350 .Pp
351 Widths over 8k are considered probable errors and not supported.
352 If
353 .Dv XOF_WARN
354 is set, a warning will be generated.
355 .Ss "Field Modifiers"
356 Field modifiers are flags which modify the way content emitted for
357 particular output styles:
358 .Bl -column M "Name123456789"
359 .It Sy M "Name          " "Description"
360 .It a "argument      " "The content appears as a ""const char *"" argument"
361 .It c "colon         " "A colon ("":"") is appended after the label"
362 .It d "display       " "Only emit field for display styles (text/HTML)"
363 .It e "encoding      " "Only emit for encoding styles (XML/JSON)"
364 .It h "humanize (hn) " "Format large numbers in human\-readable style"
365 .It " " "hn\-space     " "Humanize: Place space between numeric and unit"
366 .It " " "hn\-decimal   " "Humanize: Add a decimal digit, if number < 10"
367 .It " " "hn\-1000      " "Humanize: Use 1000 as divisor instead of 1024"
368 .It k "key           " "Field is a key, suitable for XPath predicates"
369 .It l "leaf\-list    " "Field is a leaf\-list, a list of leaf values"
370 .It n "no\-quotes    " "Do not quote the field when using JSON style"
371 .It q "quotes        " "Quote the field when using JSON style"
372 .It t "trim          " "Trim leading and trailing whitespace"
373 .It w "white space   " "A blank ("" "") is appended after the label"
374 .El
375 .Pp
376 For example, the modifier string "Lwc" means the field has a label
377 role (text that describes the next field) and should be followed by a
378 colon (\(aqc\(aq) and a space (\(aqw\(aq).
379 The modifier string "Vkq" means the
380 field has a value role, that it is a key for the current instance, and
381 that the value should be quoted when encoded for JSON.
382 .Pp
383 Roles and modifiers can also use more verbose names, when preceeded by
384 a comma.
385 For example, the modifier string "Lwc" (or "L,white,colon")
386 means the field has a label role (text that describes the next field)
387 and should be followed by a colon (\(aqc\(aq) and a space (\(aqw\(aq).
388 The modifier string "Vkq" (or ":key,quote") means the field has a value
389 role (the default role), that it is a key for the current instance,
390 and that the value should be quoted when encoded for JSON.
391 .Ss "The Argument Modifier ({a:})"
392 The argument modifier indicates that the content of the field
393 descriptor will be placed as a UTF\-8 string (const char *) argument
394 within the xo_emit parameters.
395 .Bd -literal -offset indent
396     EXAMPLE:
397       xo_emit("{La:} {a:}\\n", "Label text", "label", "value");
398     TEXT:
399       Label text value
400     JSON:
401       "label": "value"
402     XML:
403       <label>value</label>
404 .Ed
405 .Pp
406 The argument modifier allows field names for value fields to be passed
407 on the stack, avoiding the need to build a field descriptor using
408 .Xr snprintf 1 .
409 For many field roles, the argument modifier is not needed,
410 since those roles have specific mechanisms for arguments,
411 such as "{C:fg\-%s}".
412 .Ss "The Colon Modifier ({c:})"
413 The colon modifier appends a single colon to the data value:
414 .Bd -literal -offset indent
415     EXAMPLE:
416       xo_emit("{Lc:Name}{:name}\\n", "phil");
417     TEXT:
418       Name:phil
419 .Ed
420 .Pp
421 The colon modifier is only used for the TEXT and HTML output
422 styles.
423 It is commonly combined with the space modifier (\(aq{w:}\(aq).
424 It is purely a convenience feature.
425 .Ss "The Display Modifier ({d:})"
426 The display modifier indicated the field should only be generated for
427 the display output styles, TEXT and HTML.
428 .Bd -literal -offset indent
429     EXAMPLE:
430       xo_emit("{Lcw:Name}{d:name} {:id/%d}\\n", "phil", 1);
431     TEXT:
432       Name: phil 1
433     XML:
434       <id>1</id>
435 .Ed
436 .Pp
437 The display modifier is the opposite of the encoding modifier, and
438 they are often used to give to distinct views of the underlying data.
439 .Ss "The Encoding Modifier ({e:})"
440 The encoding modifier indicated the field should only be generated for
441 the encoding output styles, such as JSON and XML.
442 .Bd -literal -offset indent
443     EXAMPLE:
444       xo_emit("{Lcw:Name}{:name} {e:id/%d}\\n", "phil", 1);
445     TEXT:
446       Name: phil
447     XML:
448       <name>phil</name><id>1</id>
449 .Ed
450 .Pp
451 The encoding modifier is the opposite of the display modifier, and
452 they are often used to give to distinct views of the underlying data.
453 .Ss "The Humanize Modifier ({h:})"
454 The humanize modifier is used to render large numbers as in a
455 human\-readable format.
456 While numbers like "44470272" are completely readable to computers and
457 savants, humans will generally find "44M" more meaningful.
458 .Pp
459 "hn" can be used as an alias for "humanize".
460 .Pp
461 The humanize modifier only affects display styles (TEXT and HMTL).
462 The "no\-humanize" option will block the function of the humanize modifier.
463 .Pp
464 There are a number of modifiers that affect details of humanization.
465 These are only available in as full names, not single characters.
466 The "hn\-space" modifier places a space between the number and any
467 multiplier symbol, such as "M" or "K" (ex: "44 K").
468 The "hn\-decimal" modifier will add a decimal point and a single tenths digit
469 when the number is less than 10 (ex: "4.4K").
470 The "hn\-1000" modifier will use 1000 as divisor instead of 1024, following the
471 JEDEC\-standard instead of the more natural binary powers\-of\-two
472 tradition.
473 .Bd -literal -offset indent
474     EXAMPLE:
475         xo_emit("{h:input/%u}, {h,hn\-space:output/%u}, "
476            "{h,hn\-decimal:errors/%u}, {h,hn\-1000:capacity/%u}, "
477            "{h,hn\-decimal:remaining/%u}\\n",
478             input, output, errors, capacity, remaining);
479     TEXT:
480         21, 57 K, 96M, 44M, 1.2G
481 .Ed
482 .Pp
483 In the HTML style, the original numeric value is rendered in the
484 "data\-number" attribute on the <div> element:
485 .Bd -literal -offset indent
486     <div class="data" data\-tag="errors"
487          data\-number="100663296">96M</div>
488 .Ed
489 .Ss "The Gettext Modifier ({g:})"
490 The gettext modifier is used to translate individual fields using the
491 gettext domain (typically set using the "{G:}" role) and current
492 language settings.
493 Once libxo renders the field value, it is passed
494 to
495 .Xr gettext 3 ,
496 where it is used as a key to find the native language
497 translation.
498 .Pp
499 In the following example, the strings "State" and "full" are passed
500 to
501 .Fn gettext
502 to find locale\-based translated strings.
503 .Bd -literal -offset indent
504     xo_emit("{Lgwc:State}{g:state}\\n", "full");
505 .Ed
506 .Ss "The Key Modifier ({k:})"
507 The key modifier is used to indicate that a particular field helps
508 uniquely identify an instance of list data.
509 .Bd -literal -offset indent
510     EXAMPLE:
511         xo_open_list("user");
512         for (i = 0; i < num_users; i++) {
513             xo_open_instance("user");
514             xo_emit("User {k:name} has {:count} tickets\\n",
515                user[i].u_name, user[i].u_tickets);
516             xo_close_instance("user");
517         }
518         xo_close_list("user");
519 .Ed
520 .Pp
521 Currently the key modifier is only used when generating XPath values
522 for the HTML output style when
523 .Dv XOF_XPATH
524 is set, but other uses are likely in the near future.
525 .Ss "The Leaf\-List Modifier ({l:})"
526 The leaf\-list modifier is used to distinguish lists where each
527 instance consists of only a single value.  In XML, these are
528 rendered as single elements, where JSON renders them as arrays.
529 .Bd -literal -offset indent
530     EXAMPLE:
531         xo_open_list("user");
532         for (i = 0; i < num_users; i++) {
533             xo_emit("Member {l:name}\\n", user[i].u_name);
534         }
535         xo_close_list("user");
536     XML:
537         <user>phil</user>
538         <user>pallavi</user>
539     JSON:
540         "user": [ "phil", "pallavi" ]
541 .Ed
542 .Ss "The No\-Quotes Modifier ({n:})"
543 The no\-quotes modifier (and its twin, the \(aqquotes\(aq modifier) affect
544 the quoting of values in the JSON output style.
545 JSON uses quotes for
546 string values, but no quotes for numeric, boolean, and null data.
547 .Xr xo_emit 3
548 applies a simple heuristic to determine whether quotes are
549 needed, but often this needs to be controlled by the caller.
550 .Bd -literal -offset indent
551     EXAMPLE:
552       const char *bool = is_true ? "true" : "false";
553       xo_emit("{n:fancy/%s}", bool);
554     JSON:
555       "fancy": true
556 .Ed
557 .Ss "The Plural Modifier ({p:})"
558 The plural modifier selects the appropriate plural form of an
559 expression based on the most recent number emitted and the current
560 language settings.
561 The contents of the field should be the singular
562 and plural English values, separated by a comma:
563 .Bd -literal -offset indent
564     xo_emit("{:bytes} {Ngp:byte,bytes}\\n", bytes);
565 .Ed
566 .Pp
567 The plural modifier is meant to work with the gettext modifier ({g:})
568 but can work independently.
569 .Pp
570 When used without the gettext modifier or when the message does not
571 appear in the message catalog, the first token is chosen when the last
572 numeric value is equal to 1; otherwise the second value is used,
573 mimicking the simple pluralization rules of English.
574 .Pp
575 When used with the gettext modifier, the
576 .Xr ngettext 3
577 function is
578 called to handle the heavy lifting, using the message catalog to
579 convert the singular and plural forms into the native language.
580 .Ss "The Quotes Modifier ({q:})"
581 The quotes modifier (and its twin, the \(aqno-quotes\(aq modifier) affect
582 the quoting of values in the JSON output style.
583 JSON uses quotes for
584 string values, but no quotes for numeric, boolean, and null data.
585 .Xr xo_emit 3
586 applies a simple heuristic to determine whether quotes are
587 needed, but often this needs to be controlled by the caller.
588 .Bd -literal -offset indent
589     EXAMPLE:
590       xo_emit("{q:time/%d}", 2014);
591     JSON:
592       "year": "2014"
593 .Ed
594 .Ss "The White Space Modifier ({w:})"
595 The white space modifier appends a single space to the data value:
596 .Bd -literal -offset indent
597     EXAMPLE:
598       xo_emit("{Lw:Name}{:name}\\n", "phil");
599     TEXT:
600       Name phil
601 .Ed
602 .Pp
603 The white space modifier is only used for the TEXT and HTML output
604 styles.
605 It is commonly combined with the colon modifier (\(aq{c:}\(aq).
606 It is purely a convenience feature.
607 .Pp
608 Note that the sense of the \(aqw\(aq modifier is reversed for the units role
609 ({Uw:}); a blank is added before the contents, rather than after it.
610 .Ss "Field Formatting"
611 The field format is similar to the format string for
612 .Xr printf 3 .
613 Its use varies based on the role of the field, but generally is used to
614 format the field\(aqs contents.
615 .Pp
616 If the format string is not provided for a value field, it defaults
617 to "%s".
618 .Pp
619 Note a field definition can contain zero or more printf\-style
620 .Dq directives ,
621 which are sequences that start with a \(aq%\(aq and end with
622 one of following characters: "diouxXDOUeEfFgGaAcCsSp".
623 Each directive
624 is matched by one of more arguments to the
625 .Xr xo_emit 3
626 function.
627 .Pp
628 The format string has the form:
629 .Bd -literal -offset indent
630   \(aq%\(aq format\-modifier * format\-character
631 .Ed
632 .Pp
633 The format\- modifier can be:
634 .Bl -bullet
635 .It
636 a \(aq#\(aq character, indicating the output value should be prefixed with
637 "0x", typically to indicate a base 16 (hex) value.
638 .It
639 a minus sign (\(aq\-\(aq), indicating the output value should be padded on
640 the right instead of the left.
641 .It
642 a leading zero (\(aq0\(aq) indicating the output value should be padded on the
643 left with zeroes instead of spaces (\(aq \(aq).
644 .It
645 one or more digits (\(aq0\(aq \- \(aq9\(aq) indicating the minimum width of the
646 argument.
647 If the width in columns of the output value is less than
648 the minimum width, the value will be padded to reach the minimum.
649 .It
650 a period followed by one or more digits indicating the maximum
651 number of bytes which will be examined for a string argument, or the maximum
652 width for a non\-string argument.
653 When handling ASCII strings this
654 functions as the field width but for multi\-byte characters, a single
655 character may be composed of multiple bytes.
656 .Xr xo_emit 3
657 will never dereference memory beyond the given number of bytes.
658 .It
659 a second period followed by one or more digits indicating the maximum
660 width for a string argument.
661 This modifier cannot be given for non\-string arguments.
662 .It
663 one or more \(aqh\(aq characters, indicating shorter input data.
664 .It
665 one or more \(aql\(aq characters, indicating longer input data.
666 .It
667 a \(aqz\(aq character, indicating a \(aqsize_t\(aq argument.
668 .It
669 a \(aqt\(aq character, indicating a \(aqptrdiff_t\(aq argument.
670 .It
671 a \(aq \(aq character, indicating a space should be emitted before
672 positive numbers.
673 .It
674 a \(aq+\(aq character, indicating sign should emitted before any number.
675 .El
676 .Pp
677 Note that \(aqq\(aq, \(aqD\(aq, \(aqO\(aq, and \(aqU\(aq are considered deprecated and will be
678 removed eventually.
679 .Pp
680 The format character is described in the following table:
681 .Bl -column C "Argument Type12"
682 .It Sy "C" "Argument Type  " "Format"
683 .It d "int            " "base 10 (decimal)"
684 .It i "int            " "base 10 (decimal)"
685 .It o "int            " "base 8 (octal)"
686 .It u "unsigned       " "base 10 (decimal)"
687 .It x "unsigned       " "base 16 (hex)"
688 .It X "unsigned long  " "base 16 (hex)"
689 .It D "long           " "base 10 (decimal)"
690 .It O "unsigned long  " "base 8 (octal)"
691 .It U "unsigned long  " "base 10 (decimal)"
692 .It e "double         " "[\-]d.ddde+\-dd"
693 .It E "double         " "[\-]d.dddE+\-dd"
694 .It f "double         " "[\-]ddd.ddd"
695 .It F "double         " "[\-]ddd.ddd"
696 .It g "double         " "as \(aqe\(aq or \(aqf\(aq"
697 .It G "double         " "as \(aqE\(aq or \(aqF\(aq"
698 .It a "double         " "[\-]0xh.hhhp[+\-]d"
699 .It A "double         " "[\-]0Xh.hhhp[+\-]d"
700 .It c "unsigned char  " "a character"
701 .It C "wint_t         " "a character"
702 .It s "char *         " "a UTF\-8 string"
703 .It S "wchar_t *      " "a unicode/WCS string"
704 .It p "void *         " "\(aq%#lx\(aq"
705 .El
706 .Pp
707 The \(aqh\(aq and \(aql\(aq modifiers affect the size and treatment of the
708 argument:
709 .Bl -column "Mod" "d, i         " "o, u, x, X         "
710 .It Sy "Mod" "d, i        " "o, u, x, X"
711 .It "hh " "signed char " "unsigned char"
712 .It "h  " "short       " "unsigned short"
713 .It "l  " "long        " "unsigned long"
714 .It "ll " "long long   " "unsigned long long"
715 .It "j  " "intmax_t    " "uintmax_t"
716 .It "t  " "ptrdiff_t   " "ptrdiff_t"
717 .It "z  " "size_t      " "size_t"
718 .It "q  " "quad_t      " "u_quad_t"
719 .El
720 .Ss "UTF\-8 and Locale Strings"
721 All strings for
722 .Nm libxo
723 must be UTF\-8.
724 .Nm libxo
725 will handle turning them
726 into locale\-based strings for display to the user.
727 .Pp
728 For strings, the \(aqh\(aq and \(aql\(aq modifiers affect the interpretation of
729 the bytes pointed to argument.
730 The default \(aq%s\(aq string is a \(aqchar *\(aq
731 pointer to a string encoded as UTF\-8.
732 Since UTF\-8 is compatible with
733 .Em ASCII
734 data, a normal 7\-bit
735 .Em ASCII
736 string can be used.
737 "%ls" expects a
738 "wchar_t *" pointer to a wide\-character string, encoded as 32\-bit
739 Unicode values.
740 "%hs" expects a "char *" pointer to a multi\-byte
741 string encoded with the current locale, as given by the
742 .Ev LC_CTYPE ,
743 .Ev LANG ,
744 or
745 .Ev LC_ALL
746 environment variables.
747 The first of this list of
748 variables is used and if none of the variables are set, the locale defaults to
749 .Em UTF\-8 .
750 .Pp
751 .Nm libxo
752 will
753 convert these arguments as needed to either UTF\-8 (for XML, JSON, and
754 HTML styles) or locale\-based strings for display in text style.
755 .Bd -literal -offset indent
756    xo_emit("All strings are utf\-8 content {:tag/%ls}",
757            L"except for wide strings");
758 .Ed
759 .Pp
760 "%S" is equivalent to "%ls".
761 .Pp
762 For example, a function is passed a locale\-base name, a hat size,
763 and a time value.
764 The hat size is formatted in a UTF\-8 (ASCII)
765 string, and the time value is formatted into a wchar_t string.
766 .Bd -literal -offset indent
767     void print_order (const char *name, int size,
768                       struct tm *timep) {
769         char buf[32];
770         const char *size_val = "unknown";
771
772         if (size > 0)
773             snprintf(buf, sizeof(buf), "%d", size);
774             size_val = buf;
775         }
776
777         wchar_t when[32];
778         wcsftime(when, sizeof(when), L"%d%b%y", timep);
779
780         xo_emit("The hat for {:name/%hs} is {:size/%s}.\\n",
781                 name, size_val);
782         xo_emit("It was ordered on {:order\-time/%ls}.\\n",
783                 when);
784     }
785 .Ed
786 .Pp
787 It is important to note that
788 .Xr xo_emit 3
789 will perform the conversion
790 required to make appropriate output.
791 Text style output uses the
792 current locale (as described above), while XML, JSON, and HTML use
793 UTF\-8.
794 .Pp
795 UTF\-8 and locale\-encoded strings can use multiple bytes to encode one
796 column of data.
797 The traditional "precision" (aka "max\-width") value
798 for "%s" printf formatting becomes overloaded since it specifies both
799 the number of bytes that can be safely referenced and the maximum
800 number of columns to emit.
801 .Xr xo_emit 3
802 uses the precision as the former,
803 and adds a third value for specifying the maximum number of columns.
804 .Pp
805 In this example, the name field is printed with a minimum of 3 columns
806 and a maximum of 6.
807 Up to ten bytes are in used in filling those columns.
808 .Bd -literal -offset indent
809     xo_emit("{:name/%3.10.6s}", name);
810 .Ed
811 .Ss "Characters Outside of Field Definitions"
812 Characters in the format string that are not part of a field definition are
813 copied to the output for the TEXT style, and are ignored for the JSON
814 and XML styles.
815 For HTML, these characters are placed in a <div> with class "text".
816 .Bd -literal -offset indent
817   EXAMPLE:
818       xo_emit("The hat is {:size/%s}.\\n", size_val);
819   TEXT:
820       The hat is extra small.
821   XML:
822       <size>extra small</size>
823   JSON:
824       "size": "extra small"
825   HTML:
826       <div class="text">The hat is </div>
827       <div class="data" data\-tag="size">extra small</div>
828       <div class="text">.</div>
829 .Ed
830 .Ss "\(aq%n\(aq is Not Supported"
831 .Nm libxo
832 does not support the \(aq%n\(aq directive.
833 It is a bad idea and we
834 just do not do it.
835 .Ss "The Encoding Format (eformat)"
836 The "eformat" string is the format string used when encoding the field
837 for JSON and XML.
838 If not provided, it defaults to the primary format
839 with any minimum width removed.
840 If the primary is not given, both default to "%s".
841 .Sh EXAMPLE
842 In this example, the value for the number of items in stock is emitted:
843 .Bd -literal -offset indent
844         xo_emit("{P:   }{Lwc:In stock}{:in\-stock/%u}\\n",
845                 instock);
846 .Ed
847 .Pp
848 This call will generate the following output:
849 .Bd -literal -offset indent
850   TEXT:
851        In stock: 144
852   XML:
853       <in\-stock>144</in\-stock>
854   JSON:
855       "in\-stock": 144,
856   HTML:
857       <div class="line">
858         <div class="padding">   </div>
859         <div class="label">In stock</div>
860         <div class="decoration">:</div>
861         <div class="padding"> </div>
862         <div class="data" data\-tag="in\-stock">144</div>
863       </div>
864 .Ed
865 .Pp
866 Clearly HTML wins the verbosity award, and this output does
867 not include
868 .Dv XOF_XPATH
869 or
870 .Dv XOF_INFO
871 data, which would expand the penultimate line to:
872 .Bd -literal -offset indent
873        <div class="data" data\-tag="in\-stock"
874           data\-xpath="/top/data/item/in\-stock"
875           data\-type="number"
876           data\-help="Number of items in stock">144</div>
877 .Ed
878 .Sh WHAT MAKES A GOOD FIELD NAME?
879 To make useful, consistent field names, follow these guidelines:
880 .Ss "Use lower case, even for TLAs"
881 Lower case is more civilized.
882 Even TLAs should be lower case
883 to avoid scenarios where the differences between "XPath" and
884 "Xpath" drive your users crazy.
885 Using "xpath" is simpler and better.
886 .Ss "Use hyphens, not underscores"
887 Use of hyphens is traditional in XML, and the
888 .Dv XOF_UNDERSCORES
889 flag can be used to generate underscores in JSON, if desired.
890 But the raw field name should use hyphens.
891 .Ss "Use full words"
892 Do not abbreviate especially when the abbreviation is not obvious or
893 not widely used.
894 Use "data\-size", not "dsz" or "dsize".
895 Use
896 "interface" instead of "ifname", "if\-name", "iface", "if", or "intf".
897 .Ss "Use <verb>\-<units>"
898 Using the form <verb>\-<units> or <verb>\-<classifier>\-<units> helps in
899 making consistent, useful names, avoiding the situation where one app
900 uses "sent\-packet" and another "packets\-sent" and another
901 "packets\-we\-have\-sent".
902 The <units> can be dropped when it is
903 obvious, as can obvious words in the classification.
904 Use "receive\-after\-window\-packets" instead of
905 "received\-packets\-of\-data\-after\-window".
906 .Ss "Reuse existing field names"
907 Nothing is worse than writing expressions like:
908 .Bd -literal -offset indent
909     if ($src1/process[pid == $pid]/name ==
910         $src2/proc\-table/proc/p[process\-id == $pid]/proc\-name) {
911         ...
912     }
913 .Ed
914 .Pp
915 Find someone else who is expressing similar data and follow their
916 fields and hierarchy.
917 Remember the quote is not
918 .Dq "Consistency is the hobgoblin of little minds"
919 but
920 .Dq "A foolish consistency is the hobgoblin of little minds" .
921 .Ss "Think about your users"
922 Have empathy for your users, choosing clear and useful fields that
923 contain clear and useful data.
924 You may need to augment the display content with
925 .Xr xo_attr 3
926 calls or "{e:}" fields to make the data useful.
927 .Ss "Do not use an arbitrary number postfix"
928 What does "errors2" mean?
929 No one will know.
930 "errors\-after\-restart" would be a better choice.
931 Think of your users, and think of the future.
932 If you make "errors2", the next guy will happily make
933 "errors3" and before you know it, someone will be asking what is the
934 difference between errors37 and errors63.
935 .Ss "Be consistent, uniform, unsurprising, and predictable"
936 Think of your field vocabulary as an API.
937 You want it useful,
938 expressive, meaningful, direct, and obvious.
939 You want the client
940 application\(aqs programmer to move between without the need to
941 understand a variety of opinions on how fields are named.
942 They should
943 see the system as a single cohesive whole, not a sack of cats.
944 .Pp
945 Field names constitute the means by which client programmers interact
946 with our system.
947 By choosing wise names now, you are making their lives better.
948 .Pp
949 After using
950 .Xr xolint 1
951 to find errors in your field descriptors, use
952 .Dq "xolint \-V"
953 to spell check your field names and to detect different
954 names for the same data.
955 .Dq dropped\-short
956 and
957 .Dq dropped\-too\-short
958 are both reasonable names, but using them both will lead users to ask the
959 difference between the two fields.
960 If there is no difference,
961 use only one of the field names.
962 If there is a difference, change the
963 names to make that difference more obvious.
964 .Sh SEE ALSO
965 .Xr libxo 3 ,
966 .Xr xolint 1 ,
967 .Xr xo_emit 3