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