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 '{' [ role | modifier ]* [',' long-names ]* ':' [ content ]
55 [ '/' field-format [ '/' encoding-format ]] '}'
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 ('"in-stock": 65'), 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 preceeded 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");
227 The {G:} role allows a domain name to be set.
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
236 .Bd -literal -offset indent
237 xo_emit("{G:libc}Service unavailable in restricted mode\n");
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);
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);
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);
258 .Ss "The Title Role ({T:})"
259 Titles are heading or column headers that are meant to be displayed to
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");
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);
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.
282 flag is set, units are rendered in XML as the
285 .Bd -literal -offset indent
286 <distance units="miles">50</distance>
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>
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).
298 is the default role; if no other role designation is given, the field
300 The field name must appear within the field descriptor,
301 followed by one or two format descriptors.
303 descriptor is used for display styles (TEXT and HTML), while the
304 second one is used for encoding styles (XML and JSON).
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,
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
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.
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);
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);
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
345 If the width is zero, nothing happens.
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.
350 Widths over 8k are considered probable errors and not supported.
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"
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.
381 Roles and modifiers can also use more verbose names, when preceeded by
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
393 xo_emit("{Lc:Name}{:name}\\n", "phil");
398 The colon modifier is only used for the TEXT and HTML output
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
407 xo_emit("{Lcw:Name}{d:name} {:id/%d}\\n", "phil", 1);
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
421 xo_emit("{Lcw:Name}{:name} {e:id/%d}\\n", "phil", 1);
425 <name>phil</name><id>1</id>
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.
436 "hn" can be used as an alias for "humanize".
438 The humanize modifier only affects display styles (TEXT and HMTL).
439 The "no-humanize" option will block the function of the humanize modifier.
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
450 .Bd -literal -offset indent
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);
457 21, 57 K, 96M, 44M, 1.2G
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>
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
470 Once libxo renders the field value, it is passed
473 where it is used as a key to find the native language
476 In the following example, the strings "State" and "full" are passed
479 to find locale-based translated strings.
480 .Bd -literal -offset indent
481 xo_emit("{Lgwc:State}{g:state}\n", "full");
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
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");
495 xo_close_list("user");
498 Currently the key modifier is only used when generating XPath values
499 for the HTML output style when
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
508 xo_open_list("user");
509 for (i = 0; i < num_users; i++) {
510 xo_emit("Member {l:name}\n", user[i].u_name);
512 xo_close_list("user");
517 "user": [ "phil", "pallavi" ]
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.
523 string values, but no quotes for numeric, boolean, and null data.
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
529 const char *bool = is_true ? "true" : "false";
530 xo_emit("{n:fancy/%s}", bool);
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
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);
543 The plural modifier is meant to work with the gettext modifier ({g:})
544 but can work independently.
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.
551 When used with the gettext modifier, the
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.
560 string values, but no quotes for numeric, boolean, and null data.
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
566 xo_emit("{q:time/%d}", 2014);
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
574 xo_emit("{Lw:Name}{:name}\\n", "phil");
579 The white space modifier is only used for the TEXT and HTML output
581 It is commonly combined with the colon modifier ('{c:}').
582 It is purely a convenience feature.
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
589 Its use varies based on the role of the field, but generally is used to
590 format the field's contents.
592 If the format string is not provided for a value field, it defaults
595 Note a field definition can contain zero or more printf-style
597 which are sequences that start with a '%' and end with
598 one of following characters: "diouxXDOUeEfFgGaAcCsSp".
600 is matched by one of more arguments to the
604 The format string has the form:
605 .Bd -literal -offset indent
606 '%' format-modifier * format-character
609 The format- modifier can be:
612 a '#' character, indicating the output value should be prefixed with
613 "0x", typically to indicate a base 16 (hex) value.
615 a minus sign ('-'), indicating the output value should be padded on
616 the right instead of the left.
618 a leading zero ('0') indicating the output value should be padded on the
619 left with zeroes instead of spaces (' ').
621 one or more digits ('0' - '9') indicating the minimum width of the
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.
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.
633 will never dereference memory beyond the given number of bytes.
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.
639 one or more 'h' characters, indicating shorter input data.
641 one or more 'l' characters, indicating longer input data.
643 a 'z' character, indicating a 'size_t' argument.
645 a 't' character, indicating a 'ptrdiff_t' argument.
647 a ' ' character, indicating a space should be emitted before
650 a '+' character, indicating sign should emitted before any number.
653 Note that 'q', 'D', 'O', and 'U' are considered deprecated and will be
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'"
683 The 'h' and 'l' modifiers affect the size and treatment of the
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"
696 .Ss "UTF-8 and Locale Strings"
701 will handle turning them
702 into locale-based strings for display to the user.
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
714 "wchar_t *" pointer to a wide-character string, encoded as 32-bit
716 "%hs" expects a "char *" pointer to a multi-byte
717 string encoded with the current locale, as given by the
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
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");
736 "%S" is equivalent to "%ls".
738 For example, a function is passed a locale-base name, a hat size,
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,
746 const char *size_val = "unknown";
749 snprintf(buf, sizeof(buf), "%d", size);
754 wcsftime(when, sizeof(when), L"%d%b%y", timep);
756 xo_emit("The hat for {:name/%hs} is {:size/%s}.\\n",
758 xo_emit("It was ordered on {:order-time/%ls}.\\n",
763 It is important to note that
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
771 UTF-8 and locale-encoded strings can use multiple bytes to encode one
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.
778 uses the precision as the former,
779 and adds a third value for specifying the maximum number of columns.
781 In this example, the name field is printed with a minimum of 3 columns
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);
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
791 For HTML, these characters are placed in a <div> with class "text".
792 .Bd -literal -offset indent
794 xo_emit("The hat is {:size/%s}.\\n", size_val);
796 The hat is extra small.
798 <size>extra small</size>
800 "size": "extra small"
802 <div class="text">The hat is </div>
803 <div class="data" data-tag="size">extra small</div>
804 <div class="text">.</div>
806 .Ss "'%n' is Not Supported"
808 does not support the '%n' directive.
809 It is a bad idea and we
811 .Ss "The Encoding Format (eformat)"
812 The "eformat" string is the format string used when encoding the field
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".
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",
824 This call will generate the following output:
825 .Bd -literal -offset indent
829 <in-stock>144</in-stock>
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>
842 Clearly HTML wins the verbosity award, and this output does
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"
852 data-help="Number of items in stock">144</div>
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
865 flag can be used to generate underscores in JSON, if desired.
866 But the raw field name should use hyphens.
868 Do not abbreviate especially when the abbreviation is not obvious or
870 Use "data-size", not "dsz" or "dsize".
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) {
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"
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
902 calls or "{e:}" fields to make the data useful.
903 .Ss "Do not use an arbitrary number postfix"
904 What does "errors2" mean?
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.
914 expressive, meaningful, direct, and obvious.
916 application's programmer to move between without the need to
917 understand a variety of opinions on how fields are named.
919 see the system as a single cohesive whole, not a sack of cats.
921 Field names constitute the means by which client programmers interact
923 By choosing wise names now, you are making their lives better.
927 to find errors in your field descriptors, use
929 to spell check your field names and to detect different
930 names for the same data.
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.