Set the active glyph/color theme
Usage
logtree_theme(
theme = NULL,
overrides = list(),
compact = FALSE,
glyph_gap = NULL,
connector_gap = NULL,
wrap = NULL
)Arguments
- theme
Either a preset name to swap the whole glyph set, or a named list of per-key overrides to merge onto the currently active theme (matching the two calling styles shown in the package documentation).
NULL(the default) keeps the active preset: a preset is swapped only when you name one, so a call that sets justoverrides,compact,glyph_gap,connector_gaporwrapmerges onto whatever theme is active. Reset withlogtree_theme("unicode"). Five presets ship with the package:Preset What it is for "unicode"The default. Box-drawing connectors and coloured symbol glyphs, for an interactive terminal. "ascii"Plain ASCII, no colour. Safe for log files, CI, and non-UTF-8 terminals; also what every file sink renders through. "emoji"Emoji status glyphs (width-2 cells) over box-drawing connectors. "minimal"No connectors at all: branch,cornerandpipeare empty, so depth is carried by indentation alone (two columns per level). Lighter glyphs, dimmed times, wordless close lines.info,debugandinterruptedshare the middle dot and are told apart by colour."ci"Bracketed word glyphs ( [step],[ok],[warn],[fail], ...) over pure-ASCII connectors, with no colour in any slot – so a captured build log survives a runner that strips ANSI, and a failure greps as[fail].- overrides
A named list of per-slot overrides applied on top of
themeonce it is resolved – on top of the active theme whenthemeisNULL. An unknown slot name is an error, listing the valid ones. Each entry names only the fields to change; unspecified fields are kept from the existing entry. Status slots takeglyph,widthandcolor; the close-line statuses (done,warning,error,interrupted) also taketext. Thegroupslot takesbracket, theelapsedslot governs the time column on close lines, and the two non-glyph slotscrumbandsummarycarrylogtree_summary()'s appearance. See the slot and field tables below for the complete set.- compact
Density of the tree's per-level indentation.
FALSE(the default) keeps the normal spacing (three columns per level in the unicode theme);"medium"drops the trailing gap after each connector (two columns per level);"tight"additionally slims the branch and corner connectors to a single character (one column per level).TRUEis an alias for"tight". Compact applies to the active (console) theme and is cleared by a subsequent preset swap such aslogtree_theme("unicode").- glyph_gap
Number of spaces printed between a line's status glyph and its message text.
NULL(the default) leaves the active setting alone;1is the built-in spacing,0butts the message straight against the glyph, and2or more airs the two columns apart. Applies to every line kind – step open,Doneclose, leaf, group header and thewith_logging()run-summary line – so the message column stays aligned. Likecompact, it applies to the active (console) theme and is cleared by a subsequent preset swap such aslogtree_theme("unicode").- connector_gap
Number of spaces printed between a leaf or close line's own connector and its status glyph –
log_info()/log_warn()/ etc. lines and a step's ownDoneline, never a step's open line (which always renders flush, at anycompactdensity).NULL(the default) leaves the active setting alone, which trackscol_gap(so every built-in preset, andcompact = "medium"/"tight", render exactly as before). Set it explicitly to diverge fromcol_gap– e.g. pair it withcompact = "tight"to keep every rail column flush (col_gap = 0, including step-open lines) while still spacing leaf/close glyphs off their own connector. Likeglyph_gap, it applies to the active (console) theme and is cleared by a subsequent preset swap.- wrap
Column budget a rendered line is wrapped to, instead of letting a long message run off the right edge.
TRUEwraps atcli::console_width(), measured at render time so a terminal resized mid-run is picked up on its own – this is the console default; a positive number pins a fixed width;FALSEnever wraps, letting long lines overflow.NULL(the argument default) leaves the active setting alone.Continuation lines indent to the message column and carry the rails down, so a wrapped message still reads as one node of the tree: after a branch connector the vertical rail continues, after a corner it does not. A step-open line (and a group header) also rails its own glyph column, which is where its children hang – on a depth-1 root that is the only rail there is. A leaf's glyph column stays blank: nothing nests under a leaf. A token with no break opportunity – a long path, a URL – is split by display width rather than left to overflow, and a budget narrower than the tree is deep degrades to no wrapping rather than to an unusable one-column line. It applies to every line logtree renders, including the
logtree_summary()digest and thewith_logging()run-summary line.Like
compactandglyph_gap, it applies to the active (console) theme, and a subsequent preset swap returns it to theTRUEdefault. File sinks are never wrapped: they render through the ascii preset, and a file has no width to wrap to.
Details
An override list is keyed by slot; each slot's value is itself a named list of fields. Only the fields you name are changed – everything else is kept from the active theme.
Slots (valid names in an override / preset list):
| Slot | Applies to | Fields it accepts |
step | open / running step glyph | glyph, width, color |
info | log_info() leaf | glyph, width, color |
debug | log_debug() leaf | glyph, width, color |
success | log_success() leaf | glyph, width, color |
done | a step's own close line on a clean close | glyph, width, color, text |
warning | log_warn() / elevated step glyph | glyph, width, color, text |
error | log_error() / elevated step glyph | glyph, width, color, text |
interrupted | abnormal-exit (dimmed) glyph | glyph, width, color, text |
group | group header marker | glyph, color, bracket |
elapsed | the elapsed-time column printed on every close line | show, min, color, slow, slow_color |
trace | the optional call-site column: where in your code a line came from | show, capture, format, color |
timestamp | the optional wall-clock column printed in front of every line | format, color |
branch | child connector: the "tee" drawn before every child line | glyph, color |
corner | close-line connector: the "elbow" drawn on a step's own close line | glyph, color |
pipe | vertical rail carried down the left of nested lines | glyph, color |
crumb | logtree_summary() breadcrumb: the separator between path nodes | glyph, color, path_color |
summary | logtree_summary() divider above the digest | gap, rule, line |
success and done are separate slots that merely look the same by
default (every preset ships the same tick in both): success styles the
log_success() leaf line, done styles the Done line a step prints when
it closes cleanly. Override one and the other is untouched. A step that
closes elevated still renders warning / error / interrupted, so done
only ever governs the clean close.
The same split governs the text field, the word a close line prints before
its elapsed time. It is read from the closing status's own slot, falling back
to done's and then to the built-in "Done" – so
list(done = list(text = "Complete")) renames every close line, while
list(error = list(text = "Failed")) renames only the ones that went wrong.
success has no text of its own precisely because a clean close reads
done. text is a close-line concern only: it never touches the message a
log_warn() or log_error() leaf prints.
The trace slot is off in every preset, and deliberately so: capturing a call
site costs a frame walk and a source-reference lookup on every logged line, so
you opt in and the default path pays nothing. Switch it on with
list(trace = list(show = "problems")) to annotate only what went wrong, or
show = TRUE for every line that can carry a call site. show also takes a
vector of statuses, for when the bundle is too much: show = "error"
annotates errors and leaves tolerated warnings bare, show = c("error", "interrupted") adds the steps that never finished. The column is appended to
the message, so it wraps with it rather than shearing the tree.
The location – {file} and {line} together, separator included – is also
emitted as one terminal hyperlink pointing at the file, at that line, so a
click anywhere on it opens your editor there. Terminals without
hyperlink support print the same text unlinked, and the escape has no
printable width either way. {file} prints relative to the working directory
where the source sits under it – a bare file name is not something a
terminal can resolve.
On source references. {file} and {line} come from R's source
references, which exist only when the code was parsed with keep.source = TRUE. That is the default in an interactive session and under
devtools::load_all(), but not under plain Rscript and not for an
installed package. {fn} is always available. Rather than print NA, the
expander drops any whitespace-separated run of the template whose placeholders
are all unavailable – so the default format degrades from
pipeline.R:12 load_data() to load_data(), and a "{file}:{line}" format
degrades to no column at all. Set options(keep.source = TRUE) at the top of
a script if you want locations under Rscript.
Capturing and printing are separate: show decides what a line prints,
capture = TRUE decides that call sites are recorded whatever show
prints. list(trace = list(show = FALSE, capture = TRUE)) therefore leaves
the tree exactly as it was while giving the digest and any "json" sink
locations to work with. The order matters – capture happens as the run
unfolds, so a call site not recorded then cannot be recovered afterwards.
The timestamp slot is off in every preset for a different reason: a tree
read as it happens does not need to be told the time, and a column that is not
there is one the message has room for. It is the log read afterwards that
wants it – lining a run up against a monitoring graph, another service's log,
or a report that something broke at about half past two. Switch it on with
list(timestamp = list(format = "%H:%M:%S")).
The column is padded to a fixed width measured from a rendered sample, not
from the format string, so a format whose width varies with the value ("%B",
March one month and December the next) cannot shear the tree from one
line to the next. It counts against
the wrapping budget like any other column, and a wrapped message's
continuation rows carry a blank column rather than a repeated time – one
event happened once. logtree_summary()'s digest carries no timestamp at all:
it replays events that already happened, so stamping those lines with the time
the digest was printed would be a lie.
Two places outside the tree also report call sites when the slot is on:
logtree_summary()'s digest lines, which apply the same status filter as the
tree does, and the fn / file / line fields of a "json" sink (which
carries them whenever they were captured, regardless of show). See
logtree_sink_file() for pinning a file sink's column independently of the
console's.
Fields (valid names inside a slot):
| Field | Type | Accepted values |
glyph | character(1) | Any string, including "". In package source, non-ASCII must be written as \u/\U escapes, never literal characters. |
width | integer(1) | Rendered display width of glyph (1 for normal, 2 for emoji / wide cells). Drives column alignment and cannot be measured, so set it to the true width. Status slots only (step, info, debug, success, done, warning, error, interrupted). |
color | character, NULL, or a named list on trace | One or more cli styles, or NULL for no styling. Named colors ("red", "cyan", "silver", ...), bright variants ("br_red"), backgrounds ("bg_blue"), text styles ("bold", "italic", "dim"), or a hex string ("#ff8800"). A character vector combines styles, e.g. c("red", "bold"). On the elapsed slot it styles the time itself. On trace it also accepts a named list styling the parts of the column separately: location for a {file}/{line} run (the separator between them included – the location is one thing, styled and linked whole), fn for the function name, and base for everything else, which in the default format is the (). That is what the coloured presets ship: all of it dim, with the location in silver and fn in cyan, so the two read apart. A plain character vector on trace styles the whole column. NULL in the colourless ascii and ci presets. See cli::combine_ansi_styles(). |
text | character(1) | Close-line status slots only (done, warning, error, interrupted). The word a close line prints before its elapsed time; "" drops it, leaving the glyph and the time. Two placeholders are expanded: {label} (the closing step's own label, or a group's name) and {elapsed} (the formatted time). A template that places {elapsed} itself owns that column, so the time is not appended after it a second time. |
show | logical(1), or character on trace | On elapsed: FALSE drops the elapsed-time column entirely, default TRUE. On trace: FALSE (the default in every preset) off entirely; TRUE every line that can carry a call site; "problems" a shorthand for c("warning", "error", "interrupted"); or a vector of statuses naming exactly what to annotate – "running" (open lines), "info", "debug", "success", "warning", "error" (leaves of that status) and "interrupted" (a close line whose step unwound). show = "error" is errors without their warnings. An ordinary close line never carries one whatever the set: its site is its own open line's. Unknown tokens are dropped, and anything unrecognised reads as FALSE. |
format | character(1) | On trace: a template for the call-site column over three placeholders: {fn} (the enclosing function's name), {file} and {line} (where the log call sits). Default "{file}:{line} {fn}()". A whitespace-separated run whose placeholders are all unavailable is dropped whole, so the default degrades to load_data() rather than printing NA – see the note on source references below. On timestamp: a strftime format such as "%H:%M:%S" or "%Y-%m-%d %H:%M:%S", or NULL (the default in every preset) for no column at all. |
capture | logical(1) | trace slot only. TRUE records a call site on every line even where show prints none, for "record, print later": a quiet console whose logtree_summary() digest or "json" sink still carries locations. Default FALSE in every preset. It only ever adds – a show that asks for a column already implies capture, and capture = FALSE never takes that away. This is the one part of the feature that cannot be decided after the fact: a call site not recorded while the run happened is gone, because the frame stack it came from has unwound. |
min | numeric(1) | elapsed slot only. Hide times below this many seconds – min = 0.1 silences the 0.00s noise on trivial steps. Default 0 (show everything). |
slow | numeric(1) or NULL | elapsed slot only. Times at or over this many seconds count as slow and are styled with slow_color instead of color. NULL (the default) means nothing is ever flagged. |
slow_color | character or NULL | elapsed slot only. Styles applied to a slow time in place of color. Same accepted values as color; "yellow" in the unicode, emoji and minimal presets, NULL in the colourless ascii and ci presets. |
bracket | logical(1) | group slot only. TRUE wraps the header name in < >; default FALSE. |
path_color | character or NULL | crumb slot only. Styles the breadcrumb's path nodes, setting them apart from a leaf's message (which stays unstyled). Same accepted values as color; "bold" in the unicode and emoji presets, NULL in ascii. |
gap | integer(1) | summary slot only. Blank lines printed above the digest; 0 prints it flush against the tree. |
rule | logical(1) or character(1) | summary slot only. TRUE draws a cli::rule() labelled with the digest header, FALSE draws none, a string sets a custom title. |
line | integer(1) or character(1) | summary slot only. The rule's line, passed to cli::rule()'s line: a line type (1-8, "double", ...) or the string to repeat ("-" in the ascii preset). |
Examples
logtree_theme("ascii")
logtree_theme("unicode")
# No preset named: these merge onto the active theme, whichever it is.
logtree_theme(overrides = list(success = list(glyph = "*")))
# The close ("Done") tick is its own slot, restyled independently:
logtree_theme(list(done = list(glyph = "=", color = "silver")))
logtree_theme(list(group = list(glyph = "#", bracket = TRUE)))
logtree_theme(list(crumb = list(glyph = " / ", path_color = "cyan")))
logtree_theme(list(summary = list(gap = 2, rule = "Run report")))
# The word on a close line: every one at once, or only the failures.
logtree_theme(list(done = list(text = "Complete")))
logtree_theme(list(error = list(text = "Failed")))
logtree_theme(list(done = list(text = "{label} took {elapsed}")))
logtree_theme(list(done = list(text = ""))) # glyph + time only
# The elapsed-time column: hide the trivial, flag the slow.
logtree_theme(list(elapsed = list(min = 0.1)))
logtree_theme(list(elapsed = list(color = "silver", slow = 5,
slow_color = "red")))
logtree_theme(list(elapsed = list(show = FALSE)))
# The call-site column: off by default, loudest on the lines that matter.
logtree_theme(list(trace = list(show = "problems")))
logtree_theme(list(trace = list(show = TRUE)))
logtree_theme(list(trace = list(show = "error"))) # errors only
# Record call sites but print none: the digest can still show them.
logtree_theme(list(trace = list(show = FALSE, capture = TRUE)))
logtree_theme(list(trace = list(show = c("error", "interrupted"))))
logtree_theme(list(trace = list(show = TRUE, format = "{fn}()")))
logtree_theme(list(trace = list(format = "{file}:{line}", color = "silver")))
logtree_theme(list(trace = list(show = FALSE))) # back off again
# The wall-clock column: off by default, in front of every line when on.
logtree_theme(list(timestamp = list(format = "%H:%M:%S")))
logtree_theme(list(timestamp = list(format = "%Y-%m-%d %H:%M:%S",
color = "silver")))
logtree_theme(list(timestamp = list(format = NULL))) # back off again
# Naming one swaps the whole preset, clearing every override above.
logtree_theme("unicode")
logtree_theme("unicode", compact = "medium")
logtree_theme("unicode", compact = "tight")
# Tight rails, but with the glyph spaced off its connector.
logtree_theme("unicode", compact = "tight", connector_gap = 1)
# Spacing between the glyph and the message.
logtree_theme(glyph_gap = 0) # tightest: no space after the glyph
logtree_theme(glyph_gap = 2) # roomier message column
# Wrapping long messages (on by default, at the console width).
logtree_theme(wrap = 72) # pin a fixed width
logtree_theme(wrap = FALSE) # let long lines overflow instead
logtree_theme(wrap = TRUE) # back to the console width
# The other two presets.
logtree_theme("minimal") # no connectors: indentation only
logtree_theme("ci") # [ok] / [warn] / [fail], no colour
logtree_theme("unicode") # back to the default
