Create Formatting Instructions for the CLI Renderer

This chapter explains how to write the output definition language (ODL) statements that define how the JUNOS command-line interface (CLI) renderer displays JUNOScript-tagged output.

The resulting screen displays match the displays produced by JUNOS show commands. This chapter has the following sections:

Renderer Overview

The JUNOS XML renderer is custom-built for transforming JUNOScript-tagged data into ASCII output suitable for screen display. It has few elaborate features but is designed to be very fast. The following design characteristics contribute to its speed:

Implications of the Renderer’s Design

The main implication of the renderer’s design is that a JUNOS module must emit tags in the expected order—line by line—for the screen display to have the intended appearance. If, for example, a module emits a tag that by definition appears on the third line of the display before one that appears on the second line, the renderer displays what should be the third line above the second line. The module can, however, emit the tags for a line in any order as long as it emits all of them before emitting a tag that belongs to another line.

The following sections discuss further implications of the renderers’ design:

Emit Tags on a New Line

When there is concern that multiple tags might be merged on the same line, you can explicitly tell the renderer to emit a single tag to a line using the format emit flag. When the format emit flag is used, all fields after this tag are emitted to a new line. For more inforamtion, see Emit Field to New Line.

Omit Tags from a Line

You can omit an optional or irrelevant tag from a display line by emitting a tag that belongs to a subsequent line without emitting the irrelevant tag. To optimize the line’s appearance when tags are missing, the renderer automatically omits static text associated with the tag, such as a label. It also moves subsequent fields on the line to the left to eliminate extra blank space that indicates a missing field. (Depending on the formatting method used, you can either control when the renderer makes this adjustment, or allow it to make the adjustment automatically.) For more information, see Handle Missing Tags.

Determine Which Line Contains a Tag

The renderer must be able to determine unambiguously which display line a tag belongs to. Some JUNOS show commands have options (such as terse and verbose) that not only display different amounts of information but also use a different formatting style, such as individually labeled fields on multiple lines instead of a table with labels only in the column headers. You can use ODL to define multiple formats for the same tags, but you must use special instructions to tell the renderer which format to use when it detects a tag that belongs in more than one format. To define multiple formats, you enclose the ODL formatting statements for each format within a separate style statement, and assign a different name to each style. When the JUNOS module emits a container tag, it marks it with a junos:style attribute that names the formatting style to use. For more information, see Define Multiple Formats for the Same Tags.

Handle Multiple Tags with the Same Name

You can include a tag of the same name in multiple displays or on multiple lines in one display only if the displays or lines are associated with different levels of the tag hierarchy. In the following example, the <chassis-inventory> tag has a child container tag called <chassis-module>, which itself has a child container tag called <chassis-submodule>. Each of the three container tags contains a tag called <name>, which the renderer handles correctly only because each <name> tag is at a different level in the tag hierarchy. To make the structure clearer, the example does not include simple tags other than <name> at each level.

tag chassis-inventory {
	tag name {
		type string;
	}
		...# other simple tags in <chassis-inventory> 
	tag chassis-module {
		tag name {
			type string;
		}
		...# other simple tags in <chassis-module> 
		tag chassis-submodule {
			tag name {
				type string;
			}
			... # other simple tags in <chassis-submodule> 
		}
	}
}

The use of a <name> tag at multiple levels is not ambiguous, because the presence of container tags in the data stream makes it clear which level the <name> tag belongs to. That is, because the output from a JUNOS module is a valid XML document, a <name> tag can occur only inside one of the container tags, implying that one or more opening container tags always precede a <name> tag in the data stream. The renderer knows that a <name> tag belongs to the hierarchy level established by the most recently received container tag for which it has not yet detected the closing tag.

A few JUNOS show commands include lines that display multiple entities tagged with same tags. To format these lines, you can use the ODL fmtflag no-line-break statement as discussed in Place Repeated Formats on One Line.

Example: Handling Multiple Tags with the Same Name

The following example tag stream illustrates how the renderer disambiguates the <name> tags. The stream begins with a <chassis-inventory> tag, which has an associated display format as defined by the format statement in its ODL tag statement. For more information about format statements, see Group Formatting Instructions.

<chassis-inventory>
	<name>Chassis A</name>
	... # other tags for Chassis A 
	<chassis-module>
		<name>Module A.1</name>
		... # other tags for Module A.1 
		<chassis-submodule>
			<name>Submodule A.1.a</name>
			... # other tags for Submodule A.1.a 
		</chassis-submodule>
		<chassis-submodule>
			<name>Submodule A.1.b</name>
			... # other tags for Submodule A.1.b 
		</chassis-submodule>
		<chassis-submodule>
			<name>Submodule A.1.c</name>
			... # other tags for Submodule A.1.c 
		</chassis-submodule>
	</chassis-module>
<chassis-inventory>

When the renderer detects the first simple tag associated with the <chassis-inventory> tag, in this case the <name>Chassis A</name> tag pair, it begins assembling the display line on which the tag’s value appears. It displays lines defined in the format statement for the <chassis-inventory> tag until it detects the <chassis-module> tag, which has its own separate format statement and establishes a new hierarchy level.

As at the <chassis-inventory> hierarchy level, when the renderer detects the first simple tag defined to belong in the <chassis-module> tag’s format statement—the <name>Module A.1<name> tag—it begins assembling the display line on which the tag’s value appears. It can tell that this <name> tag belongs to the <chassis-module> hierarchy level because that tag is the container tag that precedes it most recently in the data stream. Again, the renderer displays lines defined in the <chassis-inventory> tag’s format statement until it detects a tag for which there is no field defined in the display (here, the <chassis-submodule> tag).

The process for displaying the tags associated with the first <chassis-submodule> tag (for Submodule A.1.a) is similar to that of the previous levels. A difference is that the <chassis-submodule> tag is the innermost container tag in the hierarchy. When it is open, the renderer looks for the closing </chassis-submodule> tag as an explicit signal that the set of tags at that level of the hierarchy is complete so it can emit the final line in the corresponding display. In the current example, the next opening tag is at the same hierarchy level: it is the <chassis-submodule> tag for Submodule A.1.b. It establishes a new instance at the same level and a new display, so the renderer knows that the next <name> tag belongs to that instance.

Choose a Format Type

The JUNOS CLI uses three main kinds of display formats, which are formatting frameworks for displaying information on a computer screen. If you are creating ODL statements to duplicate an existing format, this section describes in general terms how to use ODL statements to create the format from JUNOScript-tagged output. If you are creating a new display, the descriptions can help you decide which one best suits the information you are conveying. The following sections describe the three kinds of formats:

Table Formats

A table format arranges data into rows and columns, usually with a row for each entity and a column for each kind of information. Use a table format to display the same set of information about a number of entities, such as all hardware components or interfaces on a router. If the kind of information displayed in a column does not apply to an entity, you can display nothing in that cell in the table, or you can display a default value such as not applicable. If you find that there are many such exceptions, however, consider one of the other formatting styles.

The following output from the show chassis hardware command for an M20 router exemplifies the table format. There are five columns, each with a header label. Note that fields that do not apply to a component are left blank.

Item            Version Part number Serial number Description
Chassis                             20030         M20
Backplane       REV 07  710-001517  AA7940
Power supply B  REV 01  740-001465  000001        AC
Display         REV 02  710-001519  AA9704

For information about creating table formats, see Create Table Formats

Labeled Formats

A labeled format places different kinds of data on each line, usually with a descriptive label preceding the value in each field. Labeled formats are appropriate for displaying information about only one entity, or a different set of information about each of several entities. Unlike the fields in a table format, the fields on different lines of a labeled format do not generally align, except that sometimes a subgroup of lines is indented from the prevailing left margin.

The following output from the show interfaces media command exemplifies the labeled format:

Physical interface: t1-1/2/0, Enabled, Physical link is down
  Interface index: 26, ifIndex: 134
  Link-level type: PPP, MTU: 4474, Clocking: Internal
  Speed: T1, Loopback: Local, CRC: 16, Framing: ESF
Device flags: Present Running Down
...

For information about creating labeled formats, see Create Labeled Formats.

Hybrid Formats

Some existing JUNOS formats are hybrid formats. Like labeled formats, they display a different kind of data on each line and precede most fields with a label, but like table formats they align fields on various lines with one another for a "neater" appearance.

The following output from the show chassis environment fpm command exemplifies a hybrid format:

FPM status: 
  State                       Online
  FPM CMB Voltage:
    5.0 V bias           5030 mV
    8.0 V bias           8083 mV
  FPM Display Voltage:
    5.0 V bias           4998 mV
  FPM CMB temperature      34 degrees C / 93 degrees F
  FPM Display temperature  35 degrees C / 95 degrees F
  CMB Revision             12

Hybrid formats were common in earlier releases of the JUNOS Software. Under current user-interface guidelines, the table and labeled formatting styles are preferred. For information about creating hybrid formats, see Create Hybrid Formats.

Group Formatting Instructions

The format statement groups all statements that tell the CLI renderer how to generate a format, much as the tag statement groups all ODL statements that apply to a tag. A format statement appears within a tag’s tag statement. Almost always, the tag is a container tag and the substatements in the format statement specify how to display the values of its child tags. Because the child tags to which the format statement refers must already be defined, you typically place the format statement at the end of a tag statement.

Each format statement in an ODL file must have a unique name. The name makes it easy to reuse a previously defined format simply by referencing the name. The format statement’s syntax is:

tag tag-name {
	# child tag definitions here 
	format format-name {
		# format statements here 
	}
}

For information about the substatements appropriate to the different formatting methods, see Create Table Formats and Create Labeled Formats. For a list of all statements that can appear within a format statement, see Summary of Formatting Statements.

Create Table Formats

A table format arranges data into rows and columns, usually with a row for each entity and a column for each kind of information. A table format is appropriate for displaying the same set of information about a number of entities, such as all hardware components or interfaces on a router. Use the ODL statements discussed in the indicated sections to create the various parts of a table format:

Create a Table Header

To create a set of headers at the top of the table to describe the contents of the columns, use the header statement. The header statement conventionally appears first within a table’s format statement, reflecting the format of the table itself.

As shown in the following syntax statement, starting the string of headers at the left margin in the ODL source file makes it easier to verify that the fields on the lines in the subsequent picture statement line up correctly with the headers. The header string can start at the left margin because the renderer ignores the first nonescaped newline character in a header statement.

To specify the number of spaces between each header string, insert space characters by using the space bar. The number of spaces effectively sets column width. To obtain the best results on a range of display screens, limit the line width to the conventional screen width of 80 characters. To place the first row of values in the table on the line below the headers, insert a nonescaped newline at the end of the header by pressing the Return key before the concluding quotation mark and semicolon.

This statement shows four separate headers, but the statement can include as many as you need. Enclose the entire string of headers with quotation marks (" ") and conclude the statement with a semicolon.

format format-name {
	header "
header1					header2				header3								header4 
";
... 
}

The following example inserts one blank line after the six header fields in a format called interface-table-format.

format interface-table-format {
	header "
Interface                Admin Link Proto Local             Remote

";
# picture and line statements here 
}

You can also create multiline headers to accommodate subheaders or long headers that do not fit easily on one line. The following example for the show chassis fpc command creates headers for a table with eight columns. The Slot and State headers fit on one line, but each of the others appears on two lines—Temp (C), Total CPU Utilization (%), Interrupt CPU Utilization (%), Memory DRAM (MB), Heap Utilization (%), and Buffer Utilization (%).

format fpc-information-brief-format {
	header "
FPC status:
               Temp   CPU Utilization (%)   Memory      Utilization (%)
Slot State      (C)   Total     Interrupt   DRAM (MB)   Heap     Buffer
";
# picture and line statements here
}

Define Field Placement in a Table

To specify the arrangement of the fields in a table, use the picture statement, which graphically depicts the number and order of the lines in a format, the number of fields on each line, the width of each field, how text is justified in the field, and how many spaces come between it and neighboring fields. In a standard table, the formatting and kind of information in every row is the same, so the picture statement has just one line. To create the table, the renderer emits the line over and over, once for each entity. The alignment of fields in the repeated rows creates the appearance of columns in the table.

Enclose the complete picture statement with quotation marks (" ") and conclude the statement with a semicolon. It is conventional to start the string of fields at the left margin of the ODL file, to make it easier to line up the fields with the strings in the header statement, which also starts at the left margin.

To indicate the leftmost position that a value in a field can occupy, place an at-sign ( @ ) in the appropriate position on the line. To specify the field’s width and justification style, follow the @ sign with the appropriate number of one of the following symbols. The total number of symbols (one @ sign plus the specified number of another symbol) indicates the maximum number of characters that the renderer can place in the field without distorting the table’s columnar format.

The following example shows the usage:

		picture "
	Dynamically allocated memory: @>>>>>>>>>      Maximum: @>>>>>>>>
	Program data+BSS memory:      @>>>>>>>>>      Maximum: @>>>>>>>>
	Page data overhead:           @>>>>>>>>>      Maximum: @>>>>>>>>
	Page directory size:          @>>>>>>>>>      Maximum: @>>>>>>>> 
\\n                               ----------
	Total bytes in use:           @>>>>>>>>> (@% of available memory)
";

The following example shows the picture statement for the interface-table-format example begun in Create a Table Header. It defines six left-justified fields of various widths to line up with the headers created by the header statement.

format interface-table-format {
	header "
Interface    Admin Link Proto Local                Remote
";
	picture "
@<<<<<<<<<<  @<<<< @<<< @<<<< @<<<<<<<<<<<<<<<<<<< @<<<<<
";
}

Similarly, the following example extends the show chassis fpc command example begun in Create a Table Header, illustrating how the picture statement defines fields of different justification types that line up with the headers created by the header statement. Notice that all fields other than the second (which corresponds to the State header) are right-justified, so that the final character in the field is under the final letter in the header word (Slot, Total, and so on). Each of the last six fields can accommodate up to three characters. Because the header strings are wider than that, space characters are used to create blanks between the values.

format fpc-information-brief-format {
	header "
FPC status:
               Temp CPU Utilization (%) Memory    Utilization (%)
Slot State      (C) Total     Interrupt DRAM (MB) Heap     Buffer
";
	picture "
  @> @<<<<<<<<< @>>   @>>           @>>  @>>       @>>        @>>
";
}

The following illustrates how the headers and two rows of data look in the resulting table: FPC status:

               Temp CPU Utilization (%) Memory    Utilization (%)
Slot State      (C) Total     Interrupt DRAM (MB) Heap     Buffer
   0 Probed      35     1             0    8         0          2
   1 Probed      34    65             0    8         0          2

You can also use the @ sign without the symbols that explicitly set the expected number of characters in a field (>, <, and | ). Place the @ sign where you want the first character in the field to appear and use the number of spaces between it and the next @ sign to establish the width of that field. This works well if all fields in the table are left-justified and all values emitted by the JUNOS module fit within the fields. For best results, however, treat only the final field in a table in this manner. The following alternate statement for the interface-table-format format illustrates this usage, for the field under the Remote header:

format interface-table-format {
	header "
Interface    Admin Link Proto Local                Remote
";
	picture "
@<<<<<<<<<<  @<<<< @<<< @<<<< @<<<<<<<<<<<<<<<<<<< @
";
}

Map Tags to Table Fields

To define which tag’s contents appear in each field on a line, create a line statement for each line in the picture. (The picture statement defines each field’s location, but not its contents.) A line statement contains a field statement for each field on the line. Each field statement refers to a tag name, for which the tag statement must appear earlier in the file. In other words, you cannot define a tag within the field statement that refers to it. End each field statement with a semicolon. The order of the field statements indicates which tag’s value goes in which field: the first field statement maps to the first field in the picture statement, the second to the second, and so on.

The following extends the show chassis fpc command example discussed previously, illustrating how the eight field statements in the line statement map onto the eight fields in the picture statement.

format fpc-information-brief-format {
	header "
FPC status:
               Temp CPU Utilization (%) Memory    Utilization (%)
Slot State      (C) Total     Interrupt DRAM (MB) Heap     Buffer
";
	picture "
  @> @<<<<<<<<< @>>   @>>           @>>  @>>       @>>        @>>
";

	line {
		field slot;
		field state;
		field temperature;
		field cpu-total;
		field cpu-interrupt;
		field memory-dram-size;
		field memory-head-utilization;
		field memory-buffer-utilization;
	}
}

Format Mutually Exclusive Values

Some table formats include fields in which one of several possible values can appear but only one appears at a time (when the values are mutually exclusive, for instance). For proper column alignment in the table, each of the possible values must start at the same position on the line (in the same screen column) when it appears.

You preserve column alignment in this case by defining a separate tag for each possible value, adding a string of @ signs to the picture equal to the number of possible values and including the float flag on the field statement for each one. The float flag enables a value to "float" to the left on the line when tags whose @ signs precede its @ sign are missing. Using the float flag is the only way to enable all values to start at the same position because there is no way to superimpose the @ signs for all of the possible values at the same position in the picture statement. Without the float flag, the renderer leaves a blank space in the display where each missing value’s @ sign appears in the picture. With the flag, the renderer floats the value as far to the left as possible, but no farther than the screen column defined by the placement in the picture of the leftmost missing tag’s @ sign.

When listing the field statements for the various choices in the line statement, order them from least to most common. When the tags for less common choices are missing from the tag stream, the value for the tag that does occur can float to the left, its first letter appearing in the column defined by the first missing tag’s @ sign.

In the following output from the show isis interface brief command, the Level 1 DR and Level 2 DR columns are examples of table cells with mutually exclusive values. The value in each column is either the name of a designated intermediate system (at Level 1 or Level 2 as appropriate) or a string indicating the system’s status (such as Disabled).

IS-IS interface database:
Interface  L CirID Level 1 DR    Level 2 DR
lo0.0      3   0x1 crater.01     crater.01
so-1/0/0.0 2   0x9 Disabled      crater.09
so-1/1/0.0 2   0x7 Disabled      crater.07

The mutually exclusive choices in the two columns work the same way, so, for simplicity, consider just the Level 1 DR column. The two tags for the possible kinds of values displayed in the column are <isis-interface-state-one> for the status string and <dr-id-one> for the intermediate system’s hostname. In the following picture statement, the @ signs for the two tags are right next to one another, in the twentieth and twenty-first positions on the line. In the line statement, the field statement for the less common <isis-interface-state-one> tag is listed first and the dr-id-one field is marked with the float flag. Note that the float flag is placed directly after the tag name in the field statement, on the same line. This is a notational convention that makes the ODL file more concise. For more information about flag notation, see Format Lines in Labeled Formats.

format isis-interface-brief-format {
	header "
IS-IS interface database:
Interface  L CirID Level 1 DR    Level 2 DR
";
	picture "
@<<<<<<<<< @ @>>>> @@<<<<<<<<<<< @@<<<<<<<<<<<<<<
";
	line {
		field interface-name;
		field circuit-type;
		field circuit-id;
		field isis-interface-state-one;
		field dr-id-one flag float;
		field isis-interface-state-two;
		field dr-id-two flag float;
	}
}

Marking the dr-id-one field with the float flag means that when <isis-interface-state-one> is missing from the tag stream, the renderer floats the value of the <dr-id-one> tag to the left, starting it in the twentieth column of the display rather than the twenty-first. If the dr-id-one field were not marked with the float flag, it would start in the twenty-first column, and would not align correctly with the Level_1_DR header:

# Incorrect result when float flag is not used

IS-IS interface database:
Interface  L CirID Level 1 DR    Level 2 DR
lo0.0      3   0x1  crater.01     crater.01

You can use the float flag in other situations too. For example, you might want to use the same format for several kinds of routers even though some of the fields in the format do not apply to some of the equipment. For those routers, the corresponding tags are missing from the tag stream. By default, the renderer leaves a blank space in the display to represent the missing values, equal in width to the field’s @ sign and the text associated with it in the picture statement. To eliminate the extra blank space, you use the float flag on fields that follow an optional field. For more information, see When Tags Are Missing from a Labeled or Hybrid Format.

Create Labeled Formats

A labeled format places different kinds of data on each line, usually with a descriptive label preceding the value in each field. Use labeled formats to display information about only one entity, or a different set of information about each of several entities. Use the ODL statements discussed in the indicated sections to create the various parts of a labeled format:

Define the Header for a Labeled Format

To define the header for a labeled format, use the header statement. Using this statement for a labeled format is rarer than for a table format because not many labeled formats use the same descriptive header for every instance of the format. If you do use the header statement, by convention it appears first within the format statement. Enclose the header string with quotation marks (" ") and conclude the complete statement with a semicolon.

It is conventional to type a labeled format’s header statement on a single line, rather than on multiple lines as for a table’s header statement. Because the values in most labeled formats do not align with strings in the header, you usually do not need to start a labeled format’s header at the left margin in the ODL source file. Most of the time, however, you still want the first line of values to start on the line below the header. Rather than insert a nonescaped newline at the end of the header string as in a table’s header statement, you can place the string \\n (the newline character \n preceded by a backslash to escape it) at the end of the line.

The following statement illustrates the single-line syntax:

header "header text\\n";

The following example for the show chassis cos command illustrates how to define the header for a labeled format:

format keepalive-statistics-verbose-format {
	header "Keepalive statistics:\\n";
	#picture and line statements here 
}

Format Lines in Labeled Formats

Most fields in a labeled format use the following type of format:

label: value

The label is a string of text that describes the meaning of the field and is the same every time it appears. The value is the contents of the tag that is displayed in the field. Most lines have multiple fields in a comma-separated list, as in the following line:

Interface index: 5, SNMP ifIndex: 17, Generation: 3

The preferred method for creating labeled formats is with a combination of line and field statements rather than with a picture statement. The line statements define the order of lines, and flags and other auxiliary statements on the field statements define placement, the label, and trailing text for each field. If each field’s formatting style is different, you place the auxiliary statements on the individual field statements. If, however, all fields on all lines in a format use the same formatting style—as they do in many cases—you can list the auxiliary statements just once prior to the line and field statements.

It is conventional to put flags on the same line as the statements they modify, as in the following syntax statement for a field statement:

line {
	field field-name flag flag-name;
}

If there are multiple flags, it is conventional to list them on one line separated by spaces, as shown for the three flags in this syntax statement:

line {
	field field-name flag flag1 flag2 flag3;
}

Sometimes flags are combined with other statements, such as the template statement, which is used to define field formatting that cannot be achieved with flags. In this case, it is conventional to put each type of statement on its own line, using braces and semicolons as in the following example syntax:

line {
	field field-name {
		flag flag1 flag2 flag3;
		template formatting-instruction;
	}
}

The following sections describe the basic components for building lines in labeled formats:

The following sections describe how to combine flags and other statements to create common kinds of labeled formats.

Define a Field’s Label

A field’s label is the text displayed in front of the value contained in the corresponding tag. To define the label associated with a tag, use the formal-name statement on its tag statement. To specify that the label is to appear in the field where the tag’s contents are displayed, mark the field with the leading flag.

As an example, the formal-name statement in the following statement defines the label Output errors for the field in which the contents of the <output-error-count> tag are displayed.

tag output-error-count {
	type int;
	formal-name "Output errors";
}

To place a colon ( : ) after the label to separate it from the value contained in the tag, append both the colon flag and the leading flag to the field statement, rather than including the colon character at the end of the formal-name string.

Following is an example of using flags to define labels. The desired result is a set of lines that look like this:

Traffic statistics:
  Input bytes: 0
  Output bytes: 0

First use the formal-name statement to define the label text in the tag statement for each tag:

tag input-byte-count {
	type int;
	formal-name "Input bytes";
}

tag output-byte-count {
	type int;
	formal-name "Output bytes";
}

Then use the leading and colon flags on the field statement for each field to indicate that its label is defined by a formal-name statement and is to be followed by a colon. This format also uses the indent statement to indent all lines other than the header by two additional spaces. For more information, see Control Indenting.

format traffic-statistics-format {
	header "Traffic statistics:";
	indent 2;
	line {
		field input-byte-count flag leading colon;
	}
	line {
		field output-byte-count flag leading colon;
	}
}

Define Trailing Text for a Field

To define text that follows the value in a field, it is conventional to use flags. For instance, to place a comma or space after the value in a field, you append the comma or space flag to the field’s field statement. To place both a comma and space after a field, in that order, append both the comma and space flags.

If you do not use the leading flag (described in Define a Field’s Label), you can also place a colon, or a colon and space in that order, after the value in the field, by appending the colon or colon and space flags to the field statement. If you combine the leading flag and colon flag, the renderer automatically interprets the colon flag as a directive to insert a colon between the label and the value. To have a colon trail the value in a field, you must use the template statement as described in Create Field Formats that Use Alternate Punctuation.

Format Multiple Fields on a Line

For many fields in labeled formats, you can define all of the surrounding text—label and trailing text—by combining the leading, colon, comma, and space flags. Recall the example of the preferred formatting style:

Interface index: 5, SNMP ifIndex: 17, Generation: 3

To format this line using flags, first define each field’s label with a formal-name statement in the tag statement for the tag mapped to each field:

tag interface-index {
	type int;
	formal-name "Interface index";
}

tag snmp-index {
	type int;
	formal-name "SNMP ifIndex";
}

tag generation {
	type int;
	formal-name "Generation";
}

Then include the leading, colon, comma, and space flags in the format statement. To make the ODL file more concise, you can put flags that apply to all of a format’s fields in a single flag statement before the line statement, as in the following:

format interface-index-format {
	flag leading colon comma space;
	line {
		field interface-index;
		field snmp-index;
		field generation;
	}
}

Technically speaking, the comma and space flags do not apply to the final field on the line; the renderer automatically omits any trailing text defined by flag statements from the final field on a line. This enables you to list the flags just once and still obtain the desired result.

You can also use flags in both ways in the same format, placing flags that apply to all fields above the line statement and placing flags that apply to individual fields on their field statements. The union of the common and field-specific flags applies to a field. Consider the following example:

Physical interface: ip-0/3/0, Enabled, Physical link is Up

Only the first field has a label created by using the formal-name statement and leading flag. The third field instead uses the template statement to format the text that precedes the value, and the capitalize flag to capitalize the value (Up). The second field has no text preceding it at all—the string Enabled is the tag’s contents and is created by using the junos:format attribute and explicit flag. For more information about the template statement, the junos:format attribute and explicit flag, and the capitalize flag, see Create Field Formats that Use Alternate Punctuation, Display Alternate Text in a Field, and Capitalize Text in Tag, respectively.

In this example, then, the only formatting flags that apply to all fields are comma and space. First define the first field’s label with a formal-name statement on the tag statement for the tag mapped to the field. The second and third fields do not have formal-name statements.

tag name {
	type string;
	formal-name "Physical interface";
}

tag administrative-status {
	type string;
	attribute junos:format;
}

tag oper-status {
	type string;
}

Next create the following format statement. As noted, the first field uses the leading flag to refer to the label defined in the formal-name statement on its tag statement, and the colon flag to place a colon after the label. The second field uses the explicit flag and the third field uses the template statement and capitalize flag.

format physical-interface-normal-format {
	flag comma space;
	line {
		field name flag leading colon;
		field administrative-status flag explicit;
		field oper-status {
			template "Physical link is %s";
			flag capitalize;
		}
	}
}

Format Lists of Status Indicators

Some JUNOS Software commands return lists of status indicators, only some of which usually apply to an entity at a time. (These status indicators are commonly called flags, but are distinct from the flags defined by ODL flag statements.) For example, the output from several JUNOS show interface commands includes a line that displays one or more device flags to convey information about the interface’s physical device. There are about a dozen possible device flags, but usually only a few apply at the same time. In the following extract from a sample display, three device flags appear in a space-separated list:

Device flags: Present Running No-Multicast

To format this type of line, you can first define an empty tag for each device flag, and include a field statement for all of them in the single line statement. Use the space flag to place a space after each field. You cannot use the leading flag to define the line’s label (Device flags:), because if you did, the renderer would repeat the label in front of every device flag. Instead, use the header statement but do not put a newline character at the end, so that the device flags follow the header on the same line. This example also uses the capitalize flag to capitalize the device flags’ names in the display. For more information, see Capitalize Text in Tag.

format device-flags {
	header "Device flags: ";
	flag space capitalize;
	line {
		field down;
		field hear-own-xmit;
		field link-layer-down;
		field loopback;
		field loop-detected;
		field no-carrier;
		field no-multicast;
		field present;
		field promiscuous;
		field quench;
		field recv-all-multicasts;
		field running;
	}
}

You can achieve the same result even more efficiently by creating a container tag to hold the empty tags for the device flags. An appropriate name for the container tag is <device-flags>. Then define just one field statement that references the container tag, rather than defining a field statement for each device flag. Placing the space and capitalize flags before the line statement that contains the device-flags field makes them apply to all individual device flags contained in the <device-flags> tag.

format device-flags {
	header "Device flags: ";
	flag space capitalize;
	line {
		field device-flags;
	}
}

Using either the full or compressed notation, the following tag stream results in the desired display:

<device-flags>
	<present/>
	<running/>
	<no-multicast/>
</device-flags>

Device flags: Present Running No-Multicast

This example further illustrates what happens when you define a format using field statements rather than a picture statement and one or more tags is missing from the tag stream. In the present case, the tag stream includes tags for only 3 of the 12 device flags that the <device-flags> tag can contain. The renderer omits the missing nine tags and associated text (the trailing space) from the display and moves tags that follow a missing one to the left as far as possible, eliminating any extra blank spaces. For more information, see When Tags Are Missing from a Labeled or Hybrid Format.

Create Field Formats that Use Alternate Punctuation

The output from some JUNOS commands features formatting styles that you cannot achieve with flag statements. To create such formats, define the appearance of each field in a template statement appended to its field statement.

As an example, the following line from the show interfaces media command includes trailing text in the first and third fields (the string bps) and both trailing text and enclosing parentheses in the second and fourth fields. There are no flags for defining this kind of text:

Input rate: 0 bps (0 pss), Output rate: 11200 bps (1 pps)
To format these fields using the template statement, include all static text in the statement, enclosing it in quotation marks (" "). Use the string s to indicate the placement of the value within the string, as in the following:

line {
	field input-bit-rate template "Input rate: %s bps";
	field input-packet-rate template " (%s pps),";
	field output-bit-rate template "Output rate: %s bps";
	field output-packet-rate template " (%s pps)";
}

A line statement can include both fields with template statements and fields with flag statements. The following example is a variant of the one used in Format Multiple Fields on a Line to illustrate the use of flags. Its first field uses formatting that can be produced with flags, but the other fields use parentheses.

Logical interface: pe-0/3/0.0 (Index 12) (SNMP ifIndex: 38) (Generation: 17)

As before, the tag statement for the first field includes a formal-name statement. The statements for the other fields do not, because all text is to be defined in each one’s template statement.

tag logical-interface-index {
	type int;
	formal-name "Interface index";
}
tag index {
	type int;
}

tag snmp-index {
	type int;
}

tag generation {
	type int;
}

# In this format, you cannot define any common flags before the line statement
# because the flags apply only to the first field. 
format logical-interface-index-format {
	line {
		field interface-index flag leading colon space;
		field index template "(Index %s) ";
		field snmp-index template "(SNMP ifIndex %s) ";
		field generation template "(Generation %s)";
	}
}

Combine Various Formatting Styles in One Display

To create a format that uses different formatting styles on various lines, use a separate format statement for each distinct style. The lines still appear together in a single display as long as the JUNOS module emits tags in the correct order. Remember that the renderer is tag-oriented and line-oriented—it has no concept of groups of lines but rather works on a line-by-line basis even when rendering lines defined within a single format statement.

As an example, the first three lines of the following output from the show interfaces media command include multiple labeled fields per line, whereas the fourth line displays a list of status indicators:

Physical interface: ip-0/3/0, Enabled, Physical link is Up
  Interface index: 15, SNMP ifIndex: 36
  Type: IPIP, Link-level type: IP-over-IP, MTU: Unlimited, Speed: 800 mbps
  Flag: Present Running SNMP-Traps

To create this format, define two separate format statements, one called physical-interface-normal-format for the first three lines and another called format-device-flags for the fourth line. Both types of format statement are described in detail in other sections of this chapter. For information about the first type, see Format Multiple Fields on a Line and Create Field Formats that Use Alternate Punctuation. For information about the second type, see Format Lists of Status Indicators.

For brevity, the following example does not include the tag statements with formal-name statements that define the labels for fields that have the leading flag. For examples, see Define a Field’s Label. Some fields include the capitalize flag to capitalize the tag’s contents before displaying them. For more information, see Capitalize Text in Tag.

format physical-interface-normal-format {
	flag comma space;
	line {
		field name flag leading colon;
		field administrative-status flag explicit;
		field oper-status {
			template "Physical link is ";
			flag capitalize;
		}
	}
	line {
		field interface-index flag leading colon;
		field snmp-index flag leading colon;
	}
	line {
		field interface-type flag leading colon;
		field link-level-type flag leading colon;
		field mtu flag leading colon;
		field link-speed template "Speed: %s mbps";
	}
}
format format-device-flags {
	header "Device flags: ";
	flag space capitalize;
	line {
		field device-flags;
	}
}

Create Hybrid Formats

A hybrid format is one that combines features of tables and labeled formats in a single display. Most commonly, fields are labeled individually rather than by a column header, but extra spaces are used to make fields on the various lines align in the same screen column.

The current user-interface guidelines call for use of a table or labeled format for new formats, but many existing JUNOS commands produce hybrid-style output. The following output from the show interfaces command illustrates the most common kind of hybrid, in which the values on individually labelled lines align in the same screen column:

Traffic statistics:
Input bytes   :                23850            0 bps
Output bytes  :                40977            0 bps
Input  packets:                 1988            0 bps
Output packets:                 2397            0 bps

Because the header string (Traffic statistics:) does not establish any columns, it makes sense to define it on a single line (the convention for a labeled format’s header), rather than starting it at the left margin of the ODL file as you would for a table’s header:

header "Traffic statistics:\\n";

Then use a picture statement to define the formatting of the subsequent four lines. Even though the header string does not start at the left margin of the ODL file, it makes sense to start the lines in the picture there, to make it easier to line up the columns.

Use @ and > signs to define column placement, width, and justification as in a standard table. Notice that in the following example the byte counts are five digits long, whereas the packet counts are four digits. Because you usually cannot predict the number of digits that will appear in a given display, it makes sense to right-justify those fields so that the columns align correctly even with varying numbers of digits. Define enough slots in the field to accommodate the largest value you expect to display. To review the instructions for defining field width and justification, see Define Field Placement in a Table.

The complete format statement follows:

format traffic-statistics {
	header "Traffic statistics:\\n";
	indent 2;
	picture "
Input bytes   :              @>>>>>>        @>>>> bps
Output bytes  :              @>>>>>>        @>>>> bps
Input  packets:              @>>>>>>        @>>>> bps
Output packets:              @>>>>>>        @>>>> bps
";
	line {
		field input-byte-count;
		field input-bytes-per-second;
	}
	line {
		field output-byte-count;
		field output-bytes-per-second;
	}
	line {
		field input-packet-count;
		field input-packets-per-second;
	}
	line {
		field output-packet-count;
		field output-packets-per-second;
	}
}

Alternatively, you can create this format with a template statement for each field. To align the values in columns, you still must include a different number of blank spaces in each template statement. Figuring out the correct number of spaces probably requires making a table that looks much like a picture statement anyway. Even then, the template statement does not include notation like the right-justifying > sign that enables you to align columns when values vary in length. This means that the columns will not line up exactly unless all values are the same number of digits.

Fine-Tune a Field’s Appearance

You can format most of the kinds of output produced by JUNOS show commands by combining flag and template statements as described in Format Lines in Labeled Formats. There are also several other statements that you can use to modify a field’s appearance if necessary:

Emit Field to New Line

To direct the renderer to emit a field to a new line, use the emit flag on the corresponding field statement. For example:

#define RTH_BRIEF_OUTPUT
  line {
    field rt-destination flag emit
    ...
  }

You also need to place a junos:emit attribute where the newline character is required. For information on adding the junos:emit attribute, see Assign the junos:emit Attribute.

Display Alternate Text in a Field

To direct the renderer to display a value that is unrelated to the tag name or contents, use the attribute junos:format statement on the tag’s tag statement, and the explicit flag on the corresponding field statement. Consider, for example, the <administrative-status> tag, which describes an interface’s basic status. Suppose that you want to use the conventional values up and down as the tag’s contents, but on the screen you want to display the words Enabled and Disabled, which are not derived from up and down:

Interface ip-0/3/0, Enabled

First, include the attribute junos:format statement on the <administrative-status> tag’s tag statement. (The <administrative-name> tag instead has a formal-name statement as described in Define a Field’s Label.)

tag interface-name {
	type string;
	formal-name "Interface";
}
tag administrative-status {
	type string;
	attribute junos:format;
}

Then append the explicit flag to the corresponding field statement:

format interface-status-format {
	line {
		field interface-name flag leading comma space;
		field administrative-status flag explicit;
	}
}

Finally, alter the module’s C program to set the junos:format attribute on the <administrative-status> tag to Enabled when the content of the tag is up, or to Disabled when the content of the tag is down. For instructions, see Assign the junos:format Attribute.

As a result, the JUNOS module emits the following tags, and the renderer displays the string specified by the junos:format attribute rather than a value based on the tag contents.

<administrative-status junos:format="Enabled">up</administrative-status>
<administrative-status junos:format="Disabled">down</administrative-status>

Note:
The value specified by a tag’s junos:format attribute completely defines the appearance of the field that is marked with the explicit flag. You cannot combine the explicit flag with any other flags or statements that specify a field’s appearance.
You must provide a value to the junos:format attribute. If you leave the value field empty, the field is ignored in the output. The following example shows what the renderer produces with no value specified:

<connected-fpcs junos:format="">
</connected-fpcs>

The following example corrects the problem:

<connected-fpcs junos:format="abcd">asdf</connected-fpcs>

As a result, the display looks as follows:

FEB 1:
	State:             Online
	Priority:          Backup
	Connected FPC(s):  abcd  <---------
	Redundancy state:  Ready
FEB 3:
	State:             Online
	Redundancy state:  Active

Capitalize Text in Tag

To capitalize the first word of the value displayed in a field, use the capitalize flag. This flag is convenient if you want the JUNOS module to emit values in lowercase letters only (perhaps to simplify string-handling routines), but want capitalized values in the display.

For example, suppose that you want the renderer to capitalize the contents of the State field in the following format:

Slot 1 information: 
  State: Online

Use the capitalize flag on the field statement for the <state> tag. Assume that its preceding tag statement includes the formal-name statement to define its label as State (for brevity, the statement is not shown).

format fpc-state-information-format {
	line {
		field slot template "Slot %s information:";
	}
	line {
		field state flag leading colon capitalize;
	}
}

The tag stream is as follows. Notice that the string online is lowercase:

<fpc-information>
	<slot>1</slot>
	<state>online</state>
</fpc-information>

Because of the capitalize flag, the renderer capitalizes the word Online in the display:

Slot 1 information: 
  State: Online

Enable DNS Resolution of IP Addresses

The JUNOS CLI includes a resolve pipe that accepts output from a show command, resolves each IP address in the output to a hostname, and displays the converted output. To enable the renderer to resolve an IP address value, append the resolvable flag to the field statement for the value:

line {
	field peer-address flag resolvable;
}

The following examples illustrate output without and with address resolution:

user@host> show bgp group
Group Type: Internal           AS: 10458   Local AS: 10458
...
Total peers: 1                      Established: 1
192.168.1.107+179

user@host> <show bgp group | resolve
Group Type: Internal           AS: 10458   Local AS: 10458
...
Total peers: 1                      Established: 1
host107.abc.com+179

Control Indenting

To indent lines in a format from the left edge of the display screen, use the indent statement. The statement takes a single integer argument that indicates the number of spaces to insert between the left edge of the screen and the left margin of each line that has a line statement (but not the lines defined in the header statement). By convention, the indent statement appears among the initial statements inside a format statement. It makes sense to indicate its effective scope by placing it after the header statement (if that is used) and before any picture and line statements.

As an example, the following indent statement sets the prevailing left margin for the display called logical-interface-normal-format to the screen’s fourth column (inserts three spaces).

format logical-interface-normal-format {
	indent 3;
	line {
		field interface-index flag leading colon space;
		field index template "(Index %s) ";
		field snmp-index template "(SNMP ifIndex %s) ";
		field generation template "(Generation %s)";
	}
}
	}
	line {
		field encapsulation flag leading colon;
	}
}

The display that results is indented three spaces from the left margin of the screen:

      Logical interface: ge-2/3/0.0 (Index 5) (SNMP ifIndex: 17) (Generation: 3)
        Encapsulation: ENET2

Compare it with the result when no indent statement is used:

   Logical interface: ge-2/3/0.0 (Index 5) (SNMP ifIndex: 17) (Generation: 3)
     Encapsulation: ENET2

The renderer does not support relative indenting. That is, you cannot use multiple indent statements within a format statement to specify different amounts of indenting for different sets of lines. To achieve that effect, you must enclose each set of differently indented lines within its own format statement, specifying the appropriate number of spaces in the indent statement for each one. Because the renderer is tag-oriented and line-oriented, distinct format statements can still create a unitary display, as long as your JUNOS module emits tags in the appropriate order.

A related case is when a set of lines appears in more than one context but is indented a different amount in each context. For example, a set of lines might appear indented by six spaces when the detail option is used on the show interfaces command, but only by two spaces when the terse option is used. If you want to use the same format statement for those lines in both contexts, you need to create two copies of the format statement, and enclose each one in a separate style statement. For more information, see Define Multiple Formats for the Same Tags.

Define Multiple Formats for the Same Tags

Because the renderer is tag-oriented and line-oriented, it must always be able to determine unambiguously which format to construct when it detects a tag in the tag stream emitted by a JUNOS module. This implies that you cannot display the same tag in multiple formats that are defined at the same level in the tag hierarchy. For more information, see Implications of the Renderer’s Design.

Nevertheless, many JUNOS show commands have options (such as terse and verbose) that display different combinations of tags drawn from the same set of tags and also use a different formatting style, such as a labeled format for more extensive information and a table for a smaller set of information. To create multiple formats for the same tags, place the format statement for each format inside a separate style statement and assign a different name to each style as well as to each format.

The following example defines two style statements for a tag called fpc-information, which contains the output from the show chassis fpc command. The brief style encloses the format statement for the default tabular format:

tag fpc-information {
	# child tag definitions appear here
	/*
	 * "brief" style for default display format
	 */
	style brief {
		format fpc-information-brief-format {
			header "
FPC status:
               Temp CPU Utilization (%) Memory    Utilization (%)
Slot State      (C) Total     Interrupt DRAM (MB) Heap     Buffer
";
			picture "
  @> @<<<<<<<<< @>>   @>>           @>>  @>>       @>>        @>>
";

			line {
				field slot;
				field state flag capitalize;
				field temperature;
				field cpu-total;
				field cpu-interrupt;
				field memory-dram-size;
				field memory-head-utilization;
				field memory-buffer-utilization;
			}
		}
	}

The verbose style defines the format to be used when the show chassis fpc command includes the detail option. In the ODL file, it is within the same tag statement as the brief style, and is separated here for legibility only:

	/*
	 * "verbose" style for detail option’s display format
	 */
	style verbose {
		format fpc-information-verbose-format {
			picture "
Slot @ information:
  State                              @<<<<<<<<<
  Logical slot                    @>
  Temperature                     @>
  Total CPU DRAM                @>>> Mbytes
  Total SRAM                    @>>> Mbytes
  Total SDRAM                   @>>> Mbytes
  Total notification SDRAM      @>>> Mbytes
  I/O Manager ASIC information       @
";
			line {
				field slot;
			}
			line {
				field state flag capitalize;
			}
			line {
				field temperature;
			}
			line {
				field memory-dram-size;
			}
			line {
				field memory-sram-size;
			}
			line {
				field memory-sdram-size;
			}
			line {
				field memory-notification-sdram-size;
			}
			line {
				field asic-information;
			}
		}
	}
}

To have the renderer use the appropriate style, you must also alter the module’s C program to set the junos:style attribute appropriately when the corresponding command-line option is provided. The module needs to reference the #define statement that the ODL compiler records for each style statement in the module_odl.h file when the odc command line includes the –u option. The compiler bases the name of the #define statement on the tag name, converting all letters to uppercase and any hyphens to underscores. It attaches the suffix _STYLE_STYLE, where STYLE is the name assigned in the style statement, also converted to all uppercase letters.

In the current example, the ODL compiler creates the following #define statements for the brief and verbose styles associated with the <fpc-information> tag.

#define FPC_INFORMATION_STYLE_BRIEF brief
#define FPC_INFORMATION_STYLE_VERBOSE verbose

For instructions on altering a JUNOS module to include the junos:style attribute when it emits a tag, see Assign the junos:style Attribute. Note that if a JUNOS command has a default format—one that appears when no command-line option such as terse or detail is provided—the format statement for the default must also appear in a separate, named style statement. The module’s C program must explicitly set the junos:style attribute to reference the default style when no formatting options appear on the command line. This is because when multiple formatting styles are defined, the renderer has no concept of a default to use in the absence of the junos:style attribute.

It is not necessary to include an attribute junos:style statement on the ODL tag statement in which you are defining multiple formatting styles. This is in contrast to the attributes discussed in Assign XML Attributes to a Tag, which you must include in the tag statement.

Handle Missing Tags

Most of the time you can safely assume that the JUNOS module will emit all of the tags the renderer needs to complete a format, and will order them correctly. The renderer’s behavior when a tag is missing depends on whether you define the corresponding field’s format by using the picture statement (usual for table and hybrid formats) or by using flags, the template statement, or both (usual for labeled formats). You can define text to be displayed when a tag is missing, or when the JUNOS module does not return any information.

See the following sections for further discussion:

When Tags Are Missing from a Table

When you have used the picture statement to define a table format and the tag to be displayed in a field is missing from the tag stream, the renderer, by default, leaves a blank space for it, equal in width to the @ sign and the trailing symbols that specify field width and justification (>, < and |) of the missing tag. The renderer also leaves blanks for the text associated with the field, but there usually is no text because it is not conventional to define static text in a table’s cells. For more information about associated text, see When Tags Are Missing from a Labeled or Hybrid Format.

Leaving blank space for a value missing from a table is usually desirable because it preserves the table’s columnar format. Therefore, you do not need to use any special statements in a table format to handle missing values. The exception is when you want to display mutually exclusive values in a table cell. In this case, a value is missing in the sense that the router emits only one of a possible set of tags. For more information, see Format Mutually Exclusive Values.

As an example, recall the format discussed in Create Table Formats. For the sake of simplicity, the version used in that section omitted one field, which here appears third in the picture statement and maps to the <comment> tag.

format fpc-information-brief-format {
	header "
FPC status:
               Temp CPU Utilization (%) Memory    Utilization (%)
Slot State      (C) Total     Interrupt DRAM (MB) Heap     Buffer
";
	picture "
  @> @<<<<<<<<<@@>>   @>>           @>>  @>>       @>>        @>>
";

	line {
		field slot;
		field state;
		field comment template “--- %s ---”;
		field temperature;
		field cpu-total;
		field cpu-interrupt;
		field memory-dram-size;
		field memory-head-utilization;
		field memory-buffer-utilization;
	}
}

Suppose that the <comment> tag occurs in the tag stream when for some reason no information about the flexible PIC concentrator (FPC) in a slot is available. In that case, most of the other tags for that FPC are missing from the tag stream as well. In the following example, information about the first FPC is unavailable:

<fpc-information>
	<fpc>
		<slot>0</name>
		<comment>No information available>
	</fpc>
	<fpc>
		<slot>1</name>
		<state>Online</state>
		<temperature>38</temperature>
		<cpu-total>0</cpu-total>
		<cpu-interrupt>0</cpu-interrupt>
		<memory-dram-size>8</memory-dram-size>
		<memory-head-utilization>0</memory-head-utilization>
		<memory-buffer-utilization>4</memory-buffer-utilization>
	</fpc>
	<fpc>
		<slot>2</name>
		...

When the renderer receives the first <slot> tag, it begins constructing a line for the FPC in slot 0. It gathers and stores the <comment> tag because it belongs to the same line. When it detects the second <slot> tag, it immediately displays the line for the first FPC because a second <slot> tag cannot appear on the current line. It has not received any of the other tags that normally occur on a line, so it leaves blanks in their fields in the display (the effect is most obvious for the State field).

               Temp CPU Utilization (%) Memory    Utilization (%)
Slot State      (C) Total     Interrupt DRAM (MB) Heap     Buffer
  0            --- No information available ---

The renderer then gathers the tags that follow the second <slot> tag. When it detects the third <slot> tag, which signals the start of the third line, it emits the line for the FPC in slot 1.

               Temp CPU Utilization (%) Memory    Utilization (%)
Slot State      (C) Total     Interrupt DRAM (MB) Heap     Buffer
  0            --- No information available ---
  1  Online      38     0             0    8         0          4

When Tags Are Missing from a Labeled or Hybrid Format

The effect of missing tags in a labeled or hybrid format depends on how you define the format:

One reason that flag and template statements are preferred to the picture statement for labeled formats is that they result in a better-looking display when tags are missing. As an example, consider the following line from the output of the show interfaces command.

Logical interface: ge-2/3/0.0 (Index 5) (SNMP ifIndex 17) (Generation: 3)

The format statement is as follows. For brevity, the tag statements are omitted. Only the <logical-interface-index> tag uses the leading flag and so has a formal-name statement on its tag statement; the other three fields use template statements instead. For examples of formal-name statements, see Define a Field’s Label.

format logical-interface-flagged-format {
	line {
		field logical-interface-index flag leading colon space;
		field index template "(Index %s) ";
		field snmp-index template "(SNMP ifIndex %s) ";
		field generation template "(Generation %s)";
	}
}

When the <snmp-index> tag is missing from the tag stream, the renderer omits both the tag and the associated text defined in the tag’s template statement. The renderer moves the generation field to the left to eliminate extra blank space:

Logical interface: ge-2/3/0.0 (Index 5) (Generation: 3)

Similarly, if the <logical-interface-index> tag is missing, the index field moves to the left margin of the display:

(Index 5) (SNMP ifIndex 17) (Generation: 3)

In contrast, imagine that you use the following picture statement to define the format.

format logical-interface-picture-format {
	picture "Logical interface: @ (Index @) (SNMP ifIndex: @) (Generation: @)";
	line {
		field logical-interface-index;
		field index;
		field snmp-index;
		field generation;
	}
}

Now when the <snmp-index> tag is missing from the tag stream, the renderer by default leaves a blank space for that field, equal in width to the field’s @ sign and the text associated with it in the picture:

Logical interface: ge-2/3/0.0 (Index 5                     ) (Generation: 3)

Notice that there is not only a large blank space but also the closing parenthesis is missing from the index field, whereas the snmp-index field’s closing parenthesis appears in front of the generation field. This is because the renderer associates each @ sign in a picture statement with the text between it and any preceding @ sign on the line. This is so even if some of the text that follows the @ sign "logically" belongs with the value represented by the @ sign. The one exception is that text following the last @ sign on a line is associated with that sign. For the current example, the renderer uses the following associations.

Logical interface: @
 (Index @
) SNMP ifIndex: @
) (Generation: @)

Because the first closing parenthesis follows the second @ sign in the picture, the renderer associates it with the third (snmp-index) field rather than the second, and omits it when the corresponding tag is missing. Similarly, the second closing parenthesis appears after the empty snmp-index field because it follows the third @ sign in the picture and so is associated with the fourth (generation) field.

When Tags Are Out of Order

When a JUNOS module emits tags out of order, the result is similar to a missing tag. Consider a variant of the Logical interface example output discussed in When Tags Are Missing from a Labeled or Hybrid Format.

Logical interface: ge-0/3/0.0 (Index 12) (SNMP ifIndex:38) (Generation: 17)
  Encapsulation: ENET2

As previously noted, the preferred way to define the text associated with each field is to use flag and template statements. For brevity, the following example omits the tag statements because only the first and last fields have a formal-name statement that defines its label. For examples of formal-name statements, see Define a Field’s Label.

format logical-interface-normal-format {
	line {
		field interface-index flag leading colon space;
		field index template "(Index %s) ";
		field snmp-index template "(SNMP ifIndex %s) ";
		field generation template "(Generation %s)";
	}
	line {
		field encapsulation flag leading colon;
	}
}

Suppose that the renderer is gathering the tags for the first line statement and detects the <encapsulation> tag, which belongs to the second line. Because the renderer is tag-oriented and line-oriented, it immediately writes out the first line whether or not it has received all tags that belong to it. For most JUNOS commands, the ordering of lines in the format is significant, so it is important that your module emit all tags that belong together in a line statement before emitting any tags that belong to other lines.

As an example, imagine that the <encapsulation> tag occurs before the <snmp-index> tag in the tag stream:

<logical-interface>
	<name>ge-2/3/0.0</name>
	<generation>3</generation>
	<local-index>5</local-index>
	<encapsulation>ENET2<encapsulation>
	<snmp-index>17</snmp-index>
</logical-interface>\

The following shows that the resulting display is malformed. As soon as the renderer receives the <encapsulation> tag, it emits the first line. Because the <encapsulation> tag is the only one in its line statement, the renderer also emits that line immediately. It then detects the missing <snmp-index> tag. The <logical-interface> tag indicates that the tag stream is complete, so the renderer emits the first line again, this time with the contents of the <snmp-index> tag only.

Logical interface: ge-2/3/0.0 (Index 5) (Generation: 3)
  Encapsulation: ENET2
(SNMP ifIndex: 17)

Notice that the <generation> tag precedes the <local-index> tag in the tag stream, even though they appear in the opposite order on the display line. This does not cause a problem— the renderer still operates correctly when the tags grouped within a line statement occur out of order.

Define Text to Display When a Tag Is Missing

To define a string for the renderer to display in a field when the corresponding tag is missing from the tag stream, use the default statement. The default statement is useful when you want to signal explicitly that a tag is missing or provide other useful information. The string specified in the default statement replaces the field contents and associated text defined in any of the three possible ways (by flags, a template statement, or in a picture statement).

Displaying an alternate value seems especially appropriate for fields that are required in a labeled or hybrid format. As described in When Tags Are Missing from a Labeled or Hybrid Format, there is otherwise no indication that the field is missing when you define a field’s surrounding text with flag and template statements rather than in a picture (or use the float flag on fields defined in a picture) because the renderer simply omits the field and moves subsequent fields to the left to eliminate blank space.

You can also use the default statement to provide information when a tag is missing because it does not apply. The following line statement creates a display that reports the amount of down time for an interface. The second (last-down-time) field reports how long ago the interface was last down.

line {
	field down-time template "Total down time: %s sec";
	field last-down-time {
		template ", Last down: %s ago";
		default ", Last down: Never";
	}
}

Suppose that the total down time is 60 seconds, and the last outage was 30 seconds ago. The tag stream is as follows:

<down-time>60</down-time>
<last-down-time>30</last-down-time>

It results in the following display:

Total down time: 60 sec, Last down: 30 ago

When the interface has never gone down, the JUNOS module emits the <down-time> tag, but not the <last-down-time> tag:

<down-time>0</down-time>

The renderer displays the text defined by the default statement for the last-down-time field:

Total down time: 0 sec, Last down: Never

Handle Excessively Long Values

Sometimes the JUNOS module emits a value that is longer than the display can accommodate, causing the line to run off the right edge of the display screen. By default, the renderer takes no corrective action, and the terminal wraps the excessively long line by breaking the line at the right margin without concern for word boundaries. It starts the wrapped line at the left edge of the screen.

To direct the renderer to wrap text in a more logical way, use the fieldwrap or wordwrap flag. The renderer keeps the entire value of the field together in a logical way and sets the left margin of the wrapped line appropriately.

If a field has a defined width, which is generally true in tables, another possibility is that a long value overflows a field without making the entire line too long. To have the renderer shorten the value to fit, use the truncate flag.

For more information, see the indicated sections:

Wrap Complete Fields

The fieldwrap flag wraps a field’s complete contents to the next line when the current line is so long that it runs off the right edge of the screen. If you do not use this flag, the terminal wraps the string automatically but without regard for appropriate word breaks or the prevailing margin.

As an example, consider the following lines of output from the show interfaces extensive command:

Output errors: Carrier transitions: 1, Errors: 0, Collisions: 0, Drops: 0, Aged packets: 0

Suppose that the screen is narrower than usual, so that the second line reaches the right edge of the screen in the middle of the word Drops. The terminal wraps the line as shown.

Output errors: Carrier transitions: 1, Errors: 0, Collisions: 0, Dro
ps: 0, Aged packets: 0

To improve the wrapping behavior, append the fieldwrap flag to each field. It directs the renderer to move the complete contents of a field—the value and all associated text—to the next line of the display. Associated text is defined differently depending on the formatting method used. The flag and template statements associate text with a field in a straightforward way, but the rules are more involved if you use the picture statement. For more information, see When Tags Are Missing from a Labeled or Hybrid Format.

Because the renderer gathers all tags for a line before emitting it, it considers the entire line’s length when determining if it needs to wrap any fields. If the line is too long and there is more than one field marked with the fieldwrap or wordwrap flag, the renderer determines if wrapping the rightmost one is sufficient to make the line fit within the screen width. If not, it determines if wrapping the next eligible field to the left is sufficient. It continues in this manner until it determines which field it must wrap to make the remaining line short enough. It moves that field and all fields to its right down to the next line. If the moved line also runs off the right edge of the screen, the renderer repeats the process on the moved line.

Of course, the renderer must place the contents of the wrapped field further to the left than on the original line, or else the new line will also exceed the screen width. To determine where to start the wrapped field, the renderer considers each preceding field on the original line, proceeding from right to left. When it finds a preceding field that does not have the float flag, it aligns the first character of the wrapped field with the preceding field’s left margin on the original line. If none of the fields have the float flag (or all of them do, though that is not conventional), it starts the wrapped string at the original line’s left margin.

It is generally most efficient to apply the fieldwrap flag to all fields on a line by placing it directly above the line statement containing the field statements. The flag is probably not needed on the line’s first few fields, but applying it to all of them does no harm.

Example: Wrap Complete Fields

The following format statement formats the sample output from the show interfaces extensive command discussed in Wrap Complete Fields. For brevity, the tag statements with formal-name statements that define the label text for each fields’ leading flag are omitted.

format output-errors-format {
	header "Output errors:";
	indent 2;
	flag leading colon comma space fieldwrap;
	line {
		field carrier-transitions-count;
		field error-count;
		field collision-count;
		field drop-count;
		field aged-packet-count;
	}
}

Recall that the terminal is wrapping the display in the middle of the word Drops:

   Output errors:
     Carrier transitions: 1, Errors: 0, Collisions: 0, 
                                        Drops: 0, Aged packets: 0

Unlike the terminal, the renderer does not split words when wrapping, so it wraps the entire Drops field. It determines where to set the left margin for the wrapped line by considering each preceding field on the original line, starting with the adjacent field to the left (Collisions). Because that field does not have the float flag, the renderer uses its left margin as the left margin of the wrapped field:

   Output errors:
     Carrier transitions: 1, Errors: 0, Collisions: 0, 
                                        Drops: 0, Aged packets: 0

It looks like the wrapped line is also too long to fit, so the renderer wraps the Aged packets field as well:

   Output errors:
     Carrier transitions: 1, Errors: 0, Collisions: 0, 
                                        Drops: 0, 
                                        Aged packets: 0

Wrap Sections of Multiword Fields

The wordwrap flag wraps sections of a multiword value to subsequent lines when the current line is too long. The renderer divides the string at word boundaries (spaces). If the wrapped line is also too long, the renderer wraps it also, continuing in this manner until it reaches the end of the value in the field. The wrapping effectively creates a column of text.

Use the wordwrap flag only on the rightmost column in a table. If you place the flag on any column further to the left, it does not cause the renderer to write only as many characters in the column as defined by the string of @ signs and width-setting symbols in the picture. Instead, the renderer continues writing until it reaches the right edge of the screen, wraps the line, and repeats the process until it writes out the complete contents of the corresponding tag. It then displays the values for subsequent fields on the line, maintaining the spacing between fields as defined in the picture statement. Because the contents of the relevant tag are not within the defined width for its column, preserving intercolumn spacing means that the values in subsequent fields usually do not align under their column heads.

The following illustrates how to use the wordwrap flag to make the output from the show ospf statistics command include a final column that describes each packet type:

Packet type       Total      Last 5 seconds  Description
               Sent   Rec’d  Sent     Rec’d
      Hello  505739  990495     4         5  Establish and maintain
                                             neighbor relationships.
        DbD      20      26     0         0  (Database description packets)
                                             Describe the contents of
                                             the topological database.
                                             Consist of the OSPF header
                                             and other information.
      LSReq       6       5     0         0  (Link-State Request packets)
                                             Request a precise instance
                                             of the database.

To create this effect, use the wordwrap flag on the description field as shown in the following format statement. Note that the field’s name is enclosed in quotation marks because there is an ODL statement called description.

format ospf-statistics-format {
	header "
Packet type       Total      Last 5 seconds  Description
               Sent   Rec’d  Sent     Rec’d
";
	picture "
  @>>>>>>>>  @>>>>> @>>>>>>   @>>       @>>  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
";
	line {
		field packet-type;
		field total-packets-sent;
		field total-packets-received;
		field recent-packets-sent;
		field recent-packets-received;
		field “description” flag wordwrap;
	}
}

Truncate Long Values

To guarantee that a tag’s contents fit within the field width defined in the picture statement, append the truncate flag to its field statement. The renderer shortens the value by simply not displaying the characters at the end that exceed the defined field width. If you do not use the flag, the renderer displays a tag’s complete contents, even if they exceed the field width. In a table format, this distorts the columnar format.

The renderer does not indicate in any way that it has truncated a value, so it is best not to use the truncate flag on tags that contain numbers or other types of values that do not have an obvious endpoint. If the value is a single string with no spaces in it (such as a number), a better alternative is to build intelligence into the JUNOS module to transform long values appropriately before emitting them. If the value can have spaces in it, use the wordwrap flag as described in Wrap Complete Fields. Other possibilities are widening the field in the picture statement, or tolerating the rare nonalignment of columns in the table.

Control Line Breaks Around Output Blocks

You can insert a blank line before an output block that corresponds to a format statement by using the \n character in a header or picture statement. You can also control line breaks around an entire display by applying one of two fmtflag statements to the format statement. You can either insert a blank line between repetitions of a display or place multiple instances of a display on a single line with no line breaks between them. For more information, see the indicated sections:

Insert a Blank Line Between Repetitions of a Format

Several JUNOS commands report the same information about more than one entity. For example, when the show interfaces command line includes only the required options, the output includes an entry about every interface on the router. The renderer uses the same format statement repeatedly to format the information for each interface. To place a blank line before each repetition, apply the fmtflag blank-line statement.

The following is an example of the output from the show interfaces command for a router with three interfaces, so-1/0/0, so-1/1/0, and so-1/1/1. As indicated by the ellipses, several lines of information are omitted from each interface’s entry for brevity.

Physical interface: so-1/0/0, Enabled, Physical link is Down
   Interface index: 10, SNMP ifIndex: 21
   Link-level type: PPP, MTU: 4474, Clocking: Internal, SONET mode
   ...
   Active defects : LOL, LOF, LOS, SEF, AIS-L, AIS-P
   Logical interface so-1/0/0.0 (Index 4) (SNMP ifIndex 22)
     Flags: Device-down Hardware-Down Point-To-Point SNMP-Traps
     Encapsulation: PPP
     Protocol inet, MTU: 4470, Flags: Protocol-Down
       Addresses, Flags: Is-Preferred Is-Primary
         Destination: 192.168.8.193, Local: 192.168.8.21

Physical interface: so-1/1/0, Enabled, Physical link is Down
   Interface index: 11, SNMP ifIndex: 41
   ...
   Active defects : LOL, LOF, LOS, SEF, AIS-L, AIS-P

Physical interface: so-1/1/1, Enabled, Physical link is Down
   Interface index: 12, SNMP ifIndex: 42
   ...
   Active defects : LOL, LOF, LOS, SEF, AIS-L, AIS-P

To place a blank line between each repetition, include the fmtflag blank-line statement in the format statement, as in the following example. For brevity, the example omits the tag statements with formal-name statements and includes a line statement only for the format’s first line.

format physical-interface-normal-format {
	fmtflag blank-line;
	flag comma space;
	line {
		field name flag leading colon;
		field administrative-status flag explicit;
		field oper-status {
			template "Physical link is ";
			flag capitalize;
		}
	}
	# line statements for subsequent lines here 
}

Place Repeated Formats on One Line

The output from a few JUNOS show commands includes lines on which multiple entities tagged with the same tags are displayed together on one line. To format these lines, you can use the fmtflag no-line-break statement. As an example, consider this line of output from the show interfaces media command for a SONET interface:

SONET errors:
  BPI-B1: 0, BIP-B2: 0, REI-L: 0, BIP-B3: 0, REI-P: 0

Each of the five items on the second line is tagged with the same pair of tags: <media-alarm-name> for the alarm name (such as BPI-B1 for the first item) and <media-alarm-count> for the number of alarms (0 for the first item). To display more than one pair of values on the same line, you must include the fmtflag no-line-break statement, as in the following:

format sonet-error-format {
	fmtflag no-line-break;
	header "SONET Errors:\\n";
	indent 2;
	flag colon space;
	line {
		field media-alarm-name;
		field media-alarm-count;
	}
}

If you do not use the fmtflag no-line-break statement, the renderer instead puts each alarm name and count on its own line, as shown in the following.

SONET Errors:
  BPI-B1: 0
  BIP-B2: 0 
  REI-L: 0
  BIP-B3: 0
  REI-P: 0

Summary of Formatting Statements

The following table summarizes the formatting-related statements described in this chapter and specifies in which section or sections each is described.

Statement Effect Parent See section ...
attribute junos:format Specify value to display that is not derived from tag contents field Display Alternate Text in a Field
default Specify text to display when tag corresponding to a field is missing field Define Text to Display When a Tag Is Missing
field Map tag to a field in the display line Map Tags to Table Fields
Format Lines in Labeled Formats
flag capitalize Capitalize first word in tag contents field Capitalize Text in Tag
flag colon Insert colon ( : ) following the label or the tag’s contents field Define a Field’s Label
Define Trailing Text for a Field
flag comma Insert comma ( , ) following the tag’s contents field Define Define Trailing Text for a Field
flag emit Emits the tag’s contents to the CLI field Emit Tags on a New Line
flag explicit Display value provided in junos:format attribute rather than derived from tag contents field Display Alternate Text in a Field
flag fieldwrap When line is wider than screen, move entire field to next line field Wrap Complete Fields
flag float Enable field to move to the left to eliminate blank space left by missing tags field Format Mutually Exclusive Values
When Tags Are Missing from a Labeled or Hybrid Format
flag leading Insert label in front of tag’s value field Define a Field’s Label
flag space Insert space following the tag’s contents field Define Trailing Text for a Field
flag truncate Truncate tag’s value if it is wider than the field field Truncate Long Values
flag wordwrap When line is wider than screen, move some of this field to next line field Wrap Sections of Multiword Fields
fmtflag blank-line Place blank line before each repetition of a format format Insert a Blank Line Between Repetitions of a Format
fmtflag no-line-break Enable display of multiple formats on a single line format Place Repeated Formats on One Line
formal-name Define label text displayed by leading flag tag Define a Field’s Label
header Define header text at top of display format Create a Table Header
Define the Header for a Labeled Format
indent Indent entire display to the right format Control Indenting
line Group together field statements for a display line format Map Tags to Table Fields
Format Lines in Labeled Formats
picture Graphically specify formatting of data in display format Define Field Placement in a Table

style Define one of several formats for the same set of tags tag Define Multiple Formats for the Same Tags


© 2007-2009 Juniper Networks, Inc. All rights reserved. The information contained herein is confidential information of Juniper Networks, Inc., and may not be used, disclosed, distributed, modified, or copied without the prior written consent of Juniper Networks, Inc. in an express license. This information is subject to change by Juniper Networks, Inc. Juniper Networks, the Juniper Networks logo, and JUNOS are registered trademarks of Juniper Networks, Inc. in the United States and other countries. All other trademarks, service marks, registered trademarks, or registered service marks are the property of their respective owners.
Generated on Sun May 30 20:26:47 2010 for Juniper Networks Partner Solution Development Platform JUNOS SDK 10.2R1 by Doxygen 1.4.5