You can print hierarchical data as an ASCII tree, like how the package list
command works by using the print.tree()
helper. The tree()
helper accepts a top level struct where each key will reprent a top level branch in the tree using the name of the key. If the value of the key is a nested struct, items will be nested below based on the keys in that struct. For a leaf node (no children), the key can have an empty struct or an empty string as the value.
The tree helper will obey the order of the keys, so use ordered structs if the order of output is important to you.
which outputs the following:
The tree()
method also accepts a second argument which is a closure that is called for every item in the tree, returning a string to influence the formatting of that item. The closure receives
All parent keys concatenated as a single string
All parent keys as an array
So, for example, if you were outputting a tree view of file listings, where the top level key was C:/
and next level was Windows/
and the leaf node was foo.txt
, the string version of the key path would be C:/Windows/foo.txt
as passed to the closure. You can use the hierarchy to color entire parts of the tree if you wish. e.g., all items with the prefix C:/Windows/
are blue, etc.
There is no CLI equivalent to this helper since generating the input data in the needed format would be a little difficult.
The print helper contains a feature that will generate ASCII tables to print tabular data from the CLI. The easiest way to see what this looks like is to run the outdated
command in the root of a project:
There are several easy ways to call the table printer. Here are the arguments to the print.table()
method:
data
- Any type of data for the table. Each item in the array may either be an array in the correct order matching the number of headers or a struct with keys matching the headers.
includedHeaders
- A list of headers to include. Used for query inputs
headerNames
- A list/array of column headers to use instead of the default
debug
- Only print out the names of the columns and the first row values
Below are some basic examples that all produce the same CLI output:
You can pass an array of column headers as the first argument and then an array of rows, where each row contains an array with data for each column.
You can also pass an array of structs where the keys of the structs match the column names in the headers array.
If you have data already in a query object, you can pass that directly as the first parameter. The data
parameter is ignored here.
There is some basic support for applying formatting at a cell level. To do this, use the "array" version of the data and instead of providing a string for the cell value, provide a struct containing:
value
- The actual string value to print
options
- A string of print helper options- typically a color or background color
The options
can contain any color from the system-colors
command and follows the same format as the Print Helper.
You can limit the columns that display in the table regardless of whether you use an array of data or a query object by using the includeHeaders
parameter. This example outputs a sorted list of the names and version of all the Lucee Extensions installed in the CLI. (extensionList()
is a built in Lucee function that returns a query object)
If the data on a given row is too much to display in the given terminal, the table printer will automatically shrink columns based on how much "whitespace" is in them. Values which are too long to display will be truncated and ...
will appear at the end. Here is the output of the outdated
command.
If a user has a terminal so small that all the columns simply won't fit, the table printer will automatically eliminate extra columns on the right hand side of the table and insert a single column whose header and values are all ...
to show missing data. Here is the output of the outdated
command.
If you have a large list of items you need to output, you can use the print.columns()
helper. Pass an array of simple values to be printed, and columns will be created on the screen based on the widest item and the terminal width.
You can also pass a UDF as the second argument which will be called for each item in the array and can return a string with additional formatting text for the print helper to format that item. The closure receives the following arguments:
item (string) being printed
row number
column number
This example would print out a list of files in the directory, coloring all text files blue, and the rest green.
This helper is the same as the printColumns
command with the differences being the command accepts no formatting closure and will convert list data into an array or will accept a JSON array directly.
Tasks aren't required to output anything, but if you do, use the handy print
helper that lives in the variables
scope. You can output ANSI-formatted text this way. All the text you output will be stored in a "buffer" and at the end of the task it will be output to the console, or piped into the next command if necessary;
The print object has an unlimited number of methods you can call on it since it uses onMissingMethod. Here are the rules.
If the method has the word "line" in it, a new line will be added to the end of the string. If the string is empty or not provided, you'll just output a blank line.
CommandBox supports 256 colors, but some terminals only support 16 or even 8. If you use a color that the terminal doesn't support, it will be adjusted to the next closest color. If the method has one of the names of a supported color in it, the text will be colored. Here are the basic 16 color names:
Black
Maroon
Green
Olive
Navy
Magenta
Cyan
Silver
Grey
Red
Lime
Yellow
Blue
Fuchsia
Aqua
White
To view all the color names run the system-colors
command.
If the method has a valid color name preceded by the word "on", the background of the text will be that color.
onBlack
onRed
onGreen
onYellow
onBlue
onMagenta
onCyan
onWhite
etc...
When you run the system-colors command, you'll see that each of the 256 colors have a number. You can reference a color like so:
If any of the following words appear in the method, their decoration will be added. Note, not all of these work on all ANSI consoles. Blink, for instance, doesn't seem to work in Windows.
bold
underscored
blinking
reversed - Inverse of the default terminal colors
concealed
indented
indented
isn't part of the ANSI standard but rather a nice way to indent each line of output with two spaces to help clean up nested lines of output. If the string being passed in has carriage returns, each of them will be preceded by two spaces.
Any combination of the above is possible. Filler words like "text" will simply be ignored so you can make your method nice and readable. Get creative, but just don't overdo it. No one wants their console to look like a rainbow puked on it.
Some times you want to apply formatting at run time. For instance, show a status green if it's good and red if it's bad. You can pass a second string to the print helper with additional formatting that will be appended to the method name.
Depending on the value of the status
variable, that line would be the same as one of the following two lines:
If you have a task that takes a while to complete and you want to update the user right away, you can flush out everything in the buffer to the console with the .toConsole() method. Note, any text flushed to the console cannot be piped to another command.
All the methods in the print
object can be chained together to clean up your code.
If you have a string that contains ANSI formatting and you want to strip it out to just plain text, there is a function on the print helper to do this for you.