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