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