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
8 .\" # Phil Shafer, July 2014
15 .Nd content of format descriptors for xo_emit
19 uses format strings to control the rendering of data into
20 various output styles, including
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
32 .Dq "content string" ,
34 .Dq "format descriptors" .
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
42 how to format the field.
43 The field description is placed inside
44 a set of braces, with a colon
46 after the modifiers and a slash
48 before each format descriptors.
49 Text may be intermixed with
50 field descriptions within the format string.
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
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.
64 Braces can be escaped by using double braces, similar to "%%" in
66 The format string "{{braces}}" would emit "{braces}".
68 In the following example, three field descriptors appear.
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
75 function as an unsigned integer.
76 .Bd -literal -offset indent
77 xo_emit("{P: }{Lwc:In stock}{:in\-stock/%u}\\n", 65);
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).
84 While roles and modifiers typically use single character for brevity,
85 there are alternative names for each which allow more verbose
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);
93 Field roles are optional, and indicate the role and formatting of the
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"
111 .Bd -literal -offset indent
113 xo_emit("{L:Free}{D::}{P: }{:free/%u} {U:Blocks}\\n",
117 When a role is not provided, the "value" role is used as the default.
119 Roles and modifiers can also use more verbose names, when preceded by
121 .Bd -literal -offset indent
123 xo_emit("{,label:Free}{,decoration::}{,padding: }"
124 "{,value:free/%u} {,units:Blocks}\\n",
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);
134 Colors and effects remain in effect until modified by other "C"\-role
136 .Bd -literal -offset indent
137 xo_emit("{C:bold}{C:inverse}both{C:no\-bold}only inverse\\n");
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);
145 The content should be a comma\-separated list of zero or more colors or
147 .Bd -literal -offset indent
148 xo_emit("{C:bold,underline,inverse}All three{C:no\-bold,no\-inverse}\\n");
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);
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);
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"
181 The following color names are supported:
182 .Bl -column "no\-underline"
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
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);
203 .Ss "The Gettext Role ({G:})"
205 supports internationalization (i18n) through its use of
207 Use the "{G:}" role to request that the remaining part of
208 the format string, following the "{G:}" field, be handled using
212 uses the string as the key into the message catalog,
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.
218 change such as changing "/%06d" to "/%08d" should not force hand
219 inspection of all .po files.
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");
228 The {G:} role allows a domain name to be set.
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
237 .Bd -literal -offset indent
238 xo_emit("{G:libc}Service unavailable in restricted mode\\n");
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);
246 If a label needs to include a slash, it must be escaped using two
247 backslashes, one for the C compiler and one for
249 .Bd -literal -offset indent
250 xo_emit("{Lc:Low\\\\/warn level}{:level/%s}\\n", level);
252 .Ss "The Note Role ({N:})"
253 Notes are text that appears after a value.
254 .Bd -literal -offset indent
255 xo_emit("{:cost/%u} {N:per year}\\n", cost);
257 .Ss "The Padding Role ({P:})"
258 Padding represents whitespace used before and between fields.
259 The padding content can be either static, when placed directly within
260 the field descriptor, or a printf\-style format descriptor can be used,
261 if preceded by a slash ("/"):
262 .Bd -literal -offset indent
263 xo_emit("{P: }{Lwc:Cost}{:cost/%u}\\n", cost);
264 xo_emit("{P:/30s}{Lwc:Cost}{:cost/%u}\\n", "", cost);
266 .Ss "The Title Role ({T:})"
267 Titles are heading or column headers that are meant to be displayed to
269 The title can be either static, when placed directly within
270 the field descriptor, or a printf\-style format descriptor can be used,
271 if preceded by a slash ("/"):
272 .Bd -literal -offset indent
273 xo_emit("{T:Interface Statistics}\\n");
274 xo_emit("{T:/%20.20s}{T:/%6.6s}\\n", "Item Name", "Cost");
276 .Ss "The Units Role ({U:})"
277 Units are the dimension by which values are measured, such as degrees,
278 miles, bytes, and decibels.
279 The units field carries this information
280 for the previous value field.
281 .Bd -literal -offset indent
282 xo_emit("{Lwc:Distance}{:distance/%u}{Uw:miles}\\n", miles);
285 Note that the sense of the \(aqw\(aq modifier is reversed for units;
286 a blank is added before the contents, rather than after it.
290 flag is set, units are rendered in XML as the
293 .Bd -literal -offset indent
294 <distance units="miles">50</distance>
297 Units can also be rendered in HTML as the "data\-units" attribute:
298 .Bd -literal -offset indent
299 <div class="data" data\-tag="distance" data\-units="miles"
300 data\-xpath="/top/data/distance">50</div>
302 .Ss "The Value Role ({V:} and {:})"
303 The value role is used to represent the a data value that is
304 interesting for the non\-display output styles (XML and JSON).
306 is the default role; if no other role designation is given, the field
308 The field name must appear within the field descriptor,
309 followed by one or two format descriptors.
311 descriptor is used for display styles (TEXT and HTML), while the
312 second one is used for encoding styles (XML and JSON).
314 format is given, the encoding format defaults to the first format,
315 with any minimum width removed.
316 If no first format is given, both
317 format descriptors default to "%s".
318 .Bd -literal -offset indent
319 xo_emit("{:length/%02u}x{:width/%02u}x{:height/%02u}\\n",
320 length, width, height);
321 xo_emit("{:author} wrote \"{:poem}\" in {:year/%4d}\\n,
324 .Ss "The Anchor Roles ({[:} and {]:})"
325 The anchor roles allow a set of strings by be padded as a group,
326 but still be visible to
330 or stop anchor can give a field width and it can be either directly in
331 the descriptor or passed as an argument.
332 Any fields between the start
333 and stop anchor are padded to meet the minimum width given.
335 To give a width directly, encode it as the content of the anchor tag:
336 .Bd -literal -offset indent
337 xo_emit("({[:10}{:min/%d}/{:max/%d}{]:})\\n", min, max);
340 To pass a width as an argument, use "%d" as the format, which must
341 appear after the "/".
342 Note that only "%d" is supported for widths.
343 Using any other value could ruin your day.
344 .Bd -literal -offset indent
345 xo_emit("({[:/%d}{:min/%d}/{:max/%d}{]:})\\n", width, min, max);
348 If the width is negative, padding will be added on the right, suitable
349 for left justification.
350 Otherwise the padding will be added to the
351 left of the fields between the start and stop anchors, suitable for
353 If the width is zero, nothing happens.
355 number of columns of output between the start and stop anchors is less
356 than the absolute value of the given width, nothing happens.
358 Widths over 8k are considered probable errors and not supported.
361 is set, a warning will be generated.
362 .Ss "Field Modifiers"
363 Field modifiers are flags which modify the way content emitted for
364 particular output styles:
365 .Bl -column M "Name123456789"
366 .It Sy M "Name " "Description"
367 .It a "argument " "The content appears as a ""const char *"" argument"
368 .It c "colon " "A colon ("":"") is appended after the label"
369 .It d "display " "Only emit field for display styles (text/HTML)"
370 .It e "encoding " "Only emit for encoding styles (XML/JSON)"
371 .It h "humanize (hn) " "Format large numbers in human\-readable style"
372 .It " " "hn\-space " "Humanize: Place space between numeric and unit"
373 .It " " "hn\-decimal " "Humanize: Add a decimal digit, if number < 10"
374 .It " " "hn\-1000 " "Humanize: Use 1000 as divisor instead of 1024"
375 .It k "key " "Field is a key, suitable for XPath predicates"
376 .It l "leaf\-list " "Field is a leaf\-list, a list of leaf values"
377 .It n "no\-quotes " "Do not quote the field when using JSON style"
378 .It q "quotes " "Quote the field when using JSON style"
379 .It t "trim " "Trim leading and trailing whitespace"
380 .It w "white space " "A blank ("" "") is appended after the label"
383 For example, the modifier string "Lwc" means the field has a label
384 role (text that describes the next field) and should be followed by a
385 colon (\(aqc\(aq) and a space (\(aqw\(aq).
386 The modifier string "Vkq" means the
387 field has a value role, that it is a key for the current instance, and
388 that the value should be quoted when encoded for JSON.
390 Roles and modifiers can also use more verbose names, when preceded by
392 For example, the modifier string "Lwc" (or "L,white,colon")
393 means the field has a label role (text that describes the next field)
394 and should be followed by a colon (\(aqc\(aq) and a space (\(aqw\(aq).
395 The modifier string "Vkq" (or ":key,quote") means the field has a value
396 role (the default role), that it is a key for the current instance,
397 and that the value should be quoted when encoded for JSON.
398 .Ss "The Argument Modifier ({a:})"
399 The argument modifier indicates that the content of the field
400 descriptor will be placed as a UTF\-8 string (const char *) argument
401 within the xo_emit parameters.
402 .Bd -literal -offset indent
404 xo_emit("{La:} {a:}\\n", "Label text", "label", "value");
413 The argument modifier allows field names for value fields to be passed
414 on the stack, avoiding the need to build a field descriptor using
416 For many field roles, the argument modifier is not needed,
417 since those roles have specific mechanisms for arguments,
418 such as "{C:fg\-%s}".
419 .Ss "The Colon Modifier ({c:})"
420 The colon modifier appends a single colon to the data value:
421 .Bd -literal -offset indent
423 xo_emit("{Lc:Name}{:name}\\n", "phil");
428 The colon modifier is only used for the TEXT and HTML output
430 It is commonly combined with the space modifier (\(aq{w:}\(aq).
431 It is purely a convenience feature.
432 .Ss "The Display Modifier ({d:})"
433 The display modifier indicated the field should only be generated for
434 the display output styles, TEXT and HTML.
435 .Bd -literal -offset indent
437 xo_emit("{Lcw:Name}{d:name} {:id/%d}\\n", "phil", 1);
444 The display modifier is the opposite of the encoding modifier, and
445 they are often used to give to distinct views of the underlying data.
446 .Ss "The Encoding Modifier ({e:})"
447 The encoding modifier indicated the field should only be generated for
448 the encoding output styles, such as JSON and XML.
449 .Bd -literal -offset indent
451 xo_emit("{Lcw:Name}{:name} {e:id/%d}\\n", "phil", 1);
455 <name>phil</name><id>1</id>
458 The encoding modifier is the opposite of the display modifier, and
459 they are often used to give to distinct views of the underlying data.
460 .Ss "The Humanize Modifier ({h:})"
461 The humanize modifier is used to render large numbers as in a
462 human\-readable format.
463 While numbers like "44470272" are completely readable to computers and
464 savants, humans will generally find "44M" more meaningful.
466 "hn" can be used as an alias for "humanize".
468 The humanize modifier only affects display styles (TEXT and HMTL).
469 The "no\-humanize" option will block the function of the humanize modifier.
471 There are a number of modifiers that affect details of humanization.
472 These are only available in as full names, not single characters.
473 The "hn\-space" modifier places a space between the number and any
474 multiplier symbol, such as "M" or "K" (ex: "44 K").
475 The "hn\-decimal" modifier will add a decimal point and a single tenths digit
476 when the number is less than 10 (ex: "4.4K").
477 The "hn\-1000" modifier will use 1000 as divisor instead of 1024, following the
478 JEDEC\-standard instead of the more natural binary powers\-of\-two
480 .Bd -literal -offset indent
482 xo_emit("{h:input/%u}, {h,hn\-space:output/%u}, "
483 "{h,hn\-decimal:errors/%u}, {h,hn\-1000:capacity/%u}, "
484 "{h,hn\-decimal:remaining/%u}\\n",
485 input, output, errors, capacity, remaining);
487 21, 57 K, 96M, 44M, 1.2G
490 In the HTML style, the original numeric value is rendered in the
491 "data\-number" attribute on the <div> element:
492 .Bd -literal -offset indent
493 <div class="data" data\-tag="errors"
494 data\-number="100663296">96M</div>
496 .Ss "The Gettext Modifier ({g:})"
497 The gettext modifier is used to translate individual fields using the
498 gettext domain (typically set using the "{G:}" role) and current
500 Once libxo renders the field value, it is passed
503 where it is used as a key to find the native language
506 In the following example, the strings "State" and "full" are passed
509 to find locale\-based translated strings.
510 .Bd -literal -offset indent
511 xo_emit("{Lgwc:State}{g:state}\\n", "full");
513 .Ss "The Key Modifier ({k:})"
514 The key modifier is used to indicate that a particular field helps
515 uniquely identify an instance of list data.
516 .Bd -literal -offset indent
518 xo_open_list("user");
519 for (i = 0; i < num_users; i++) {
520 xo_open_instance("user");
521 xo_emit("User {k:name} has {:count} tickets\\n",
522 user[i].u_name, user[i].u_tickets);
523 xo_close_instance("user");
525 xo_close_list("user");
528 Currently the key modifier is only used when generating XPath values
529 for the HTML output style when
531 is set, but other uses are likely in the near future.
532 .Ss "The Leaf\-List Modifier ({l:})"
533 The leaf\-list modifier is used to distinguish lists where each
534 instance consists of only a single value. In XML, these are
535 rendered as single elements, where JSON renders them as arrays.
536 .Bd -literal -offset indent
538 xo_open_list("user");
539 for (i = 0; i < num_users; i++) {
540 xo_emit("Member {l:name}\\n", user[i].u_name);
542 xo_close_list("user");
547 "user": [ "phil", "pallavi" ]
549 .Ss "The No\-Quotes Modifier ({n:})"
550 The no\-quotes modifier (and its twin, the \(aqquotes\(aq modifier) affect
551 the quoting of values in the JSON output style.
553 string values, but no quotes for numeric, boolean, and null data.
555 applies a simple heuristic to determine whether quotes are
556 needed, but often this needs to be controlled by the caller.
557 .Bd -literal -offset indent
559 const char *bool = is_true ? "true" : "false";
560 xo_emit("{n:fancy/%s}", bool);
564 .Ss "The Plural Modifier ({p:})"
565 The plural modifier selects the appropriate plural form of an
566 expression based on the most recent number emitted and the current
568 The contents of the field should be the singular
569 and plural English values, separated by a comma:
570 .Bd -literal -offset indent
571 xo_emit("{:bytes} {Ngp:byte,bytes}\\n", bytes);
574 The plural modifier is meant to work with the gettext modifier ({g:})
575 but can work independently.
577 When used without the gettext modifier or when the message does not
578 appear in the message catalog, the first token is chosen when the last
579 numeric value is equal to 1; otherwise the second value is used,
580 mimicking the simple pluralization rules of English.
582 When used with the gettext modifier, the
585 called to handle the heavy lifting, using the message catalog to
586 convert the singular and plural forms into the native language.
587 .Ss "The Quotes Modifier ({q:})"
588 The quotes modifier (and its twin, the \(aqno-quotes\(aq modifier) affect
589 the quoting of values in the JSON output style.
591 string values, but no quotes for numeric, boolean, and null data.
593 applies a simple heuristic to determine whether quotes are
594 needed, but often this needs to be controlled by the caller.
595 .Bd -literal -offset indent
597 xo_emit("{q:time/%d}", 2014);
601 .Ss "The White Space Modifier ({w:})"
602 The white space modifier appends a single space to the data value:
603 .Bd -literal -offset indent
605 xo_emit("{Lw:Name}{:name}\\n", "phil");
610 The white space modifier is only used for the TEXT and HTML output
612 It is commonly combined with the colon modifier (\(aq{c:}\(aq).
613 It is purely a convenience feature.
615 Note that the sense of the \(aqw\(aq modifier is reversed for the units role
616 ({Uw:}); a blank is added before the contents, rather than after it.
617 .Ss "Field Formatting"
618 The field format is similar to the format string for
620 Its use varies based on the role of the field, but generally is used to
621 format the field\(aqs contents.
623 If the format string is not provided for a value field, it defaults
626 Note a field definition can contain zero or more printf\-style
628 which are sequences that start with a \(aq%\(aq and end with
629 one of following characters: "diouxXDOUeEfFgGaAcCsSp".
631 is matched by one of more arguments to the
635 The format string has the form:
636 .Bd -literal -offset indent
637 \(aq%\(aq format\-modifier * format\-character
640 The format\-modifier can be:
643 a \(aq#\(aq character, indicating the output value should be prefixed with
644 "0x", typically to indicate a base 16 (hex) value.
646 a minus sign (\(aq\-\(aq), indicating the output value should be padded on
647 the right instead of the left.
649 a leading zero (\(aq0\(aq) indicating the output value should be padded on the
650 left with zeroes instead of spaces (\(aq \(aq).
652 one or more digits (\(aq0\(aq \- \(aq9\(aq) indicating the minimum width of the
654 If the width in columns of the output value is less than
655 the minimum width, the value will be padded to reach the minimum.
657 a period followed by one or more digits indicating the maximum
658 number of bytes which will be examined for a string argument, or the maximum
659 width for a non\-string argument.
660 When handling ASCII strings this
661 functions as the field width but for multi\-byte characters, a single
662 character may be composed of multiple bytes.
664 will never dereference memory beyond the given number of bytes.
666 a second period followed by one or more digits indicating the maximum
667 width for a string argument.
668 This modifier cannot be given for non\-string arguments.
670 one or more \(aqh\(aq characters, indicating shorter input data.
672 one or more \(aql\(aq characters, indicating longer input data.
674 a \(aqz\(aq character, indicating a \(aqsize_t\(aq argument.
676 a \(aqt\(aq character, indicating a \(aqptrdiff_t\(aq argument.
678 a \(aq \(aq character, indicating a space should be emitted before
681 a \(aq+\(aq character, indicating sign should emitted before any number.
684 Note that \(aqq\(aq, \(aqD\(aq, \(aqO\(aq, and \(aqU\(aq are considered deprecated and will be
687 The format character is described in the following table:
688 .Bl -column C "Argument Type12"
689 .It Sy "C" "Argument Type " "Format"
690 .It d "int " "base 10 (decimal)"
691 .It i "int " "base 10 (decimal)"
692 .It o "int " "base 8 (octal)"
693 .It u "unsigned " "base 10 (decimal)"
694 .It x "unsigned " "base 16 (hex)"
695 .It X "unsigned long " "base 16 (hex)"
696 .It D "long " "base 10 (decimal)"
697 .It O "unsigned long " "base 8 (octal)"
698 .It U "unsigned long " "base 10 (decimal)"
699 .It e "double " "[\-]d.ddde+\-dd"
700 .It E "double " "[\-]d.dddE+\-dd"
701 .It f "double " "[\-]ddd.ddd"
702 .It F "double " "[\-]ddd.ddd"
703 .It g "double " "as \(aqe\(aq or \(aqf\(aq"
704 .It G "double " "as \(aqE\(aq or \(aqF\(aq"
705 .It a "double " "[\-]0xh.hhhp[+\-]d"
706 .It A "double " "[\-]0Xh.hhhp[+\-]d"
707 .It c "unsigned char " "a character"
708 .It C "wint_t " "a character"
709 .It s "char * " "a UTF\-8 string"
710 .It S "wchar_t * " "a unicode/WCS string"
711 .It p "void * " "\(aq%#lx\(aq"
714 The \(aqh\(aq and \(aql\(aq modifiers affect the size and treatment of the
716 .Bl -column "Mod" "d, i " "o, u, x, X "
717 .It Sy "Mod" "d, i " "o, u, x, X"
718 .It "hh " "signed char " "unsigned char"
719 .It "h " "short " "unsigned short"
720 .It "l " "long " "unsigned long"
721 .It "ll " "long long " "unsigned long long"
722 .It "j " "intmax_t " "uintmax_t"
723 .It "t " "ptrdiff_t " "ptrdiff_t"
724 .It "z " "size_t " "size_t"
725 .It "q " "quad_t " "u_quad_t"
727 .Ss "UTF\-8 and Locale Strings"
732 will handle turning them
733 into locale\-based strings for display to the user.
735 For strings, the \(aqh\(aq and \(aql\(aq modifiers affect the interpretation of
736 the bytes pointed to argument.
737 The default \(aq%s\(aq string is a \(aqchar *\(aq
738 pointer to a string encoded as UTF\-8.
739 Since UTF\-8 is compatible with
741 data, a normal 7\-bit
745 "wchar_t *" pointer to a wide\-character string, encoded as 32\-bit
747 "%hs" expects a "char *" pointer to a multi\-byte
748 string encoded with the current locale, as given by the
753 environment variables.
754 The first of this list of
755 variables is used and if none of the variables are set, the locale defaults to
760 convert these arguments as needed to either UTF\-8 (for XML, JSON, and
761 HTML styles) or locale\-based strings for display in text style.
762 .Bd -literal -offset indent
763 xo_emit("All strings are utf\-8 content {:tag/%ls}",
764 L"except for wide strings");
767 "%S" is equivalent to "%ls".
769 For example, a function is passed a locale\-base name, a hat size,
771 The hat size is formatted in a UTF\-8 (ASCII)
772 string, and the time value is formatted into a wchar_t string.
773 .Bd -literal -offset indent
774 void print_order (const char *name, int size,
777 const char *size_val = "unknown";
780 snprintf(buf, sizeof(buf), "%d", size);
785 wcsftime(when, sizeof(when), L"%d%b%y", timep);
787 xo_emit("The hat for {:name/%hs} is {:size/%s}.\\n",
789 xo_emit("It was ordered on {:order\-time/%ls}.\\n",
794 It is important to note that
796 will perform the conversion
797 required to make appropriate output.
798 Text style output uses the
799 current locale (as described above), while XML, JSON, and HTML use
802 UTF\-8 and locale\-encoded strings can use multiple bytes to encode one
804 The traditional "precision" (aka "max\-width") value
805 for "%s" printf formatting becomes overloaded since it specifies both
806 the number of bytes that can be safely referenced and the maximum
807 number of columns to emit.
809 uses the precision as the former,
810 and adds a third value for specifying the maximum number of columns.
812 In this example, the name field is printed with a minimum of 3 columns
814 Up to ten bytes are in used in filling those columns.
815 .Bd -literal -offset indent
816 xo_emit("{:name/%3.10.6s}", name);
818 .Ss "Characters Outside of Field Definitions"
819 Characters in the format string that are not part of a field definition are
820 copied to the output for the TEXT style, and are ignored for the JSON
822 For HTML, these characters are placed in a <div> with class "text".
823 .Bd -literal -offset indent
825 xo_emit("The hat is {:size/%s}.\\n", size_val);
827 The hat is extra small.
829 <size>extra small</size>
831 "size": "extra small"
833 <div class="text">The hat is </div>
834 <div class="data" data\-tag="size">extra small</div>
835 <div class="text">.</div>
837 .Ss "\(aq%n\(aq is Not Supported"
839 does not support the \(aq%n\(aq directive.
840 It is a bad idea and we
842 .Ss "The Encoding Format (eformat)"
843 The "eformat" string is the format string used when encoding the field
845 If not provided, it defaults to the primary format
846 with any minimum width removed.
847 If the primary is not given, both default to "%s".
849 In this example, the value for the number of items in stock is emitted:
850 .Bd -literal -offset indent
851 xo_emit("{P: }{Lwc:In stock}{:in\-stock/%u}\\n",
855 This call will generate the following output:
856 .Bd -literal -offset indent
860 <in\-stock>144</in\-stock>
865 <div class="padding"> </div>
866 <div class="label">In stock</div>
867 <div class="decoration">:</div>
868 <div class="padding"> </div>
869 <div class="data" data\-tag="in\-stock">144</div>
873 Clearly HTML wins the verbosity award, and this output does
878 data, which would expand the penultimate line to:
879 .Bd -literal -offset indent
880 <div class="data" data\-tag="in\-stock"
881 data\-xpath="/top/data/item/in\-stock"
883 data\-help="Number of items in stock">144</div>
885 .Sh WHAT MAKES A GOOD FIELD NAME?
886 To make useful, consistent field names, follow these guidelines:
887 .Ss "Use lower case, even for TLAs"
888 Lower case is more civilized.
889 Even TLAs should be lower case
890 to avoid scenarios where the differences between "XPath" and
891 "Xpath" drive your users crazy.
892 Using "xpath" is simpler and better.
893 .Ss "Use hyphens, not underscores"
894 Use of hyphens is traditional in XML, and the
896 flag can be used to generate underscores in JSON, if desired.
897 But the raw field name should use hyphens.
899 Do not abbreviate especially when the abbreviation is not obvious or
901 Use "data\-size", not "dsz" or "dsize".
903 "interface" instead of "ifname", "if\-name", "iface", "if", or "intf".
904 .Ss "Use <verb>\-<units>"
905 Using the form <verb>\-<units> or <verb>\-<classifier>\-<units> helps in
906 making consistent, useful names, avoiding the situation where one app
907 uses "sent\-packet" and another "packets\-sent" and another
908 "packets\-we\-have\-sent".
909 The <units> can be dropped when it is
910 obvious, as can obvious words in the classification.
911 Use "receive\-after\-window\-packets" instead of
912 "received\-packets\-of\-data\-after\-window".
913 .Ss "Reuse existing field names"
914 Nothing is worse than writing expressions like:
915 .Bd -literal -offset indent
916 if ($src1/process[pid == $pid]/name ==
917 $src2/proc\-table/proc/p[process\-id == $pid]/proc\-name) {
922 Find someone else who is expressing similar data and follow their
923 fields and hierarchy.
924 Remember the quote is not
925 .Dq "Consistency is the hobgoblin of little minds"
927 .Dq "A foolish consistency is the hobgoblin of little minds" .
928 .Ss "Think about your users"
929 Have empathy for your users, choosing clear and useful fields that
930 contain clear and useful data.
931 You may need to augment the display content with
933 calls or "{e:}" fields to make the data useful.
934 .Ss "Do not use an arbitrary number postfix"
935 What does "errors2" mean?
937 "errors\-after\-restart" would be a better choice.
938 Think of your users, and think of the future.
939 If you make "errors2", the next guy will happily make
940 "errors3" and before you know it, someone will be asking what is the
941 difference between errors37 and errors63.
942 .Ss "Be consistent, uniform, unsurprising, and predictable"
943 Think of your field vocabulary as an API.
945 expressive, meaningful, direct, and obvious.
947 application\(aqs programmer to move between without the need to
948 understand a variety of opinions on how fields are named.
950 see the system as a single cohesive whole, not a sack of cats.
952 Field names constitute the means by which client programmers interact
954 By choosing wise names now, you are making their lives better.
958 to find errors in your field descriptors, use
960 to spell check your field names and to detect different
961 names for the same data.
964 .Dq dropped\-too\-short
965 are both reasonable names, but using them both will lead users to ask the
966 difference between the two fields.
967 If there is no difference,
968 use only one of the field names.
969 If there is a difference, change the
970 names to make that difference more obvious.
978 library first appeared in
983 .An Phil Shafer Aq Mt phil@freebsd.org .