Back to skills
SKILL.md
2549 Inline Markup 1ed5cb03
BSecurity1. [Introduction](#introduction) 2. [Basic Syntax](#basic-syntax) 3. [Code & Syntax Classes](#code--syntax-classes) 4. [Files & Paths Classes](#files--paths-classes) 5. [Communication Classes](#communication-classes) 6. [Values & Data Classes](#values--data-classes) 7. [Emphasis Classes](#emphasis-classes) 8. [Documentation Classes](#documentation-classes) 9. [Special Classes](#special-classes) 10. [Vector Collapsing](#vector-collapsing) 11. [Advanced Patterns](#advanced-patterns) 12. [Pluraliza
- 9 stars
- 0 votes
- 0 copies
- 0 views
- Added October 11, 2026
Works with
Security analysis
88/100- Accesses sensitive system or user directories
npx -y skills add tools-only/X-Skills --skill 2549-inline-markup_1ed5cb03 --agent claude-codeAre you the author of 2549 Inline Markup 1ed5cb03?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/tools-only-2549-inline-markup-1ed5cb03)# CLI Inline Markup Reference
## Table of Contents
1. [Introduction](#introduction)
2. [Basic Syntax](#basic-syntax)
3. [Code & Syntax Classes](#code--syntax-classes)
4. [Files & Paths Classes](#files--paths-classes)
5. [Communication Classes](#communication-classes)
6. [Values & Data Classes](#values--data-classes)
7. [Emphasis Classes](#emphasis-classes)
8. [Documentation Classes](#documentation-classes)
9. [Special Classes](#special-classes)
10. [Vector Collapsing](#vector-collapsing)
11. [Advanced Patterns](#advanced-patterns)
12. [Pluralization](#pluralization)
13. [Performance Considerations](#performance-considerations)
14. [Quick Reference Table](#quick-reference-table)
## Introduction
Read this file when you need to:
- Look up the correct inline markup class for specific content types
- Understand how to nest and combine markup classes
- Learn vector collapsing behavior and customization
- Master pluralization patterns beyond basic `{?s}`
- Optimize performance for high-frequency messaging
- Troubleshoot unexpected formatting behavior
Inline markup classes format text within cli messages using `{.class content}` syntax. They integrate with glue string interpolation and work across all cli functions: `cli_text()`, `cli_abort()`, `cli_warn()`, `cli_inform()`, `cli_alert_*()`, etc.
## Basic Syntax
Inline markup uses curly braces with a period-prefixed class name:
```r
cli_text("Function {.fn mean} calculates {.field average}")
#> Function `mean()` calculates average
```
**Key syntax rules:**
- Format: `{.class content}`
- Content is interpolated if it contains `{}`
- Double braces `{{` and `}}` escape literal braces
- Whitespace inside `{}` is preserved in output
- Classes can be nested (see [Advanced Patterns](#advanced-patterns))
## Code & Syntax Classes
### .code
Generic code formatting for expressions, statements, or syntax:
```r
cli_text("Use {.code sum(x, na.rm = TRUE)} to ignore NA values")
cli_text("Set {.code options(width = 120)} in your .Rprofile")
cli_text("The {.code return()} statement exits early")
```
**When to use:**
- Multi-token code expressions
- Syntax examples
- Configuration snippets
- When other code classes are too specific
### .fn and .fun
Function names with automatic parentheses:
```r
cli_text("Call {.fn mean} to calculate average")
#> Call `mean()` to calculate average
cli_text("Use {.fun base::mean} for namespace clarity")
#> Use `base::mean()` for namespace clarity
```
**Automatic formatting:**
- Adds `()` suffix automatically
- Supports `package::function` notation
- Both `.fn` and `.fun` are equivalent
**When to use:**
- Referring to functions by name
- Suggesting which function to call
- Error messages about function usage
### .arg
Function argument names:
```r
cli_abort(c(
"{.arg x} must be numeric",
"i" = "Set {.arg na.rm = TRUE} to handle missing values"
))
```
**When to use:**
- Parameter validation errors
- Documenting function arguments
- Explaining argument behavior
### .cls
S3/S4/R6 class names:
```r
cli_abort("Expected {.cls data.frame}, got {.cls {class(x)}}")
cli_text("Object is {.cls tbl_df}, a tibble subclass")
```
**When to use:**
- Type checking errors
- Documenting expected types
- Explaining inheritance
### .type
Broader type descriptions (base types, generic categories):
```r
cli_abort("Input must be {.type integer}, not {.type {typeof(x)}}")
cli_text("Coercing from {.type character} to {.type numeric}")
```
**When to use:**
- Base R types: integer, double, character, logical
- Generic type categories
- Type coercion messages
### .obj_type_friendly
User-friendly type descriptions with indefinite articles:
```r
x <- data.frame()
cli_text("{.var x} must be a vector, not {.obj_type_friendly {x}}")
#> `x` must be a vector, not a data frame
y <- 1:10
cli_text("You provided {.obj_type_friendly {y}}")
#> You provided an integer vector
```
**Automatic features:**
- Adds "a"/"an" article automatically
- Uses friendly names ("data frame" not "data.frame")
- Handles pluralization for vectors
## Files & Paths Classes
### .file
File names and paths with appropriate formatting:
```r
cli_text("Reading {.file data/input.csv}")
cli_warn("File {.file ~/.ssh/config} has insecure permissions")
cli_inform("Created {.file output/results.xlsx}")
```
**Best practices:**
- Use for any file reference
- Works with relative and absolute paths
- Handles home directory expansion
### .path
Directory paths and file system locations:
```r
cli_text("Installing to {.path /usr/local/lib/R}")
cli_text("Working directory: {.path {getwd()}}")
cli_abort("Directory {.path {dir}} does not exist")
```
**When to use .file vs .path:**
- `.file` - Files, scripts, documents
- `.path` - Directories, installation locations, system paths
## Communication Classes
### .email
Email addresses:
```r
cli_text("Contact maintainer at {.email user@example.com}")
cli_inform("Send bug reports to {.email bugs@r-project.org}")
```
**Features:**
- Creates `mailto:` links in supported terminals
- Formatted distinctly from regular text
### .url
Web URLs and URIs:
```r
cli_text("Visit {.url https://cli.r-lib.org} for documentation")
cli_text("API endpoint: {.url https://api.example.com/v1}")
```
**Features:**
- Creates clickable hyperlinks in supported terminals
- Formats protocol, domain, and path distinctly
### .href
Custom hyperlinks with separate text and URL:
```r
cli_text("See {.href [documentation](https://cli.r-lib.org)}")
cli_text("Read {.href [vignette](vignette:cli::inline-markup)}")
```
**Syntax:**
- Format: `{.href [text](url)}`
- Markdown-style link syntax
- Text and URL can be styled differently
**Link types:**
- HTTP/HTTPS: `https://example.com`
- Help topics: `help:topic`
- Vignettes: `vignette:package::topic`
## Values & Data Classes
### .val
Data values, constants, and literals:
```r
n <- 42
cli_text("Found {.val {n}} records")
cli_text("Default timeout is {.val 30} seconds")
cli_text("Status: {.val 'complete'}")
```
**Automatic formatting:**
- Quoted for character values
- Unquoted for numeric values
- Handles vectors with collapsing
### .var
Variable names in code or data:
```r
cli_abort("Variable {.var x} must be numeric")
cli_text("Column {.var age} contains missing values")
cli_inform("Using {.var Sepal.Length} as predictor")
```
**When to use:**
- Variable names in R code
- Column names in data frames
- Field names in objects
### .envvar
Environment variable names:
```r
cli_text("Set {.envvar R_LIBS_USER} to customize library location")
cli_abort("{.envvar HOME} is not defined")
cli_inform("Using {.envvar PATH}: {.val {Sys.getenv('PATH')}}")
```
**When to use:**
- System environment variables
- R-specific environment variables
- Configuration via environment
### .field
Object fields, slots, or attributes:
```r
cli_text("The {.field name} field is required")
cli_abort("Invalid {.field status} value")
cli_text("Access {.field @data} slot in S4 object")
```
**When to use:**
- Named list elements
- Data frame columns (prefer `.var` for analysis context)
- S4 slots
- Object attributes
### .str
String literals and text values:
```r
cli_text("Message starts with {.str 'Error:'}")
cli_text("Pattern {.str '^[0-9]+$'} matches digits")
```
**When to use:**
- Literal string values
- Pattern strings
- Format strings
- When `.val` formatting is too generic
## Emphasis Classes
### .emph
Emphasis for important concepts or terms:
```r
cli_text("This function is {.emph deprecated}")
cli_text("The file is {.emph locked} by another process")
cli_inform("{.emph Note}: This may take several minutes")
```
**Rendering:**
- Typically italic or colored
- Lighter emphasis than `.strong`
### .strong
Strong emphasis for critical information:
```r
cli_warn("{.strong Warning}: This action cannot be undone")
cli_text("This parameter is {.strong required}")
cli_abort("{.strong Error}: Database connection failed")
```
**Rendering:**
- Typically bold or brightly colored
- Stronger emphasis than `.emph`
## Documentation Classes
### .help
R help topic references:
```r
cli_text("See {.help stats::lm} for details")
cli_inform("More info: {.help base::sum}")
```
**Features:**
- Creates link to help topic in RStudio
- Supports `package::topic` notation
- Fallback to plain text in terminals
### .topic
Generic topic or section references:
```r
cli_text("See {.topic 'Error Handling'} section")
cli_inform("Refer to {.topic 'Advanced Usage'}")
```
**When to use:**
- Internal documentation sections
- Vignette sections
- General topic references
### .vignette
Vignette references:
```r
cli_text("Read {.vignette cli::semantic-cli} for examples")
cli_inform("See {.vignette dplyr::programming}")
```
**Features:**
- Links to package vignettes
- Format: `package::vignette-name`
### .run
Runnable R code examples:
```r
cli_text("Try: {.run install.packages('cli')}")
cli_inform("Debug with: {.run options(error = recover)}")
```
**Features:**
- Creates executable link in RStudio
- Click to run code in console
- Formatted as code in terminals
## Special Classes
### .kbd
Keyboard keys and shortcuts:
```r
cli_text("Press {.kbd Ctrl+C} to cancel")
cli_text("Use {.kbd Enter} to confirm")
cli_inform("Save with {.kbd Cmd+S} (Mac) or {.kbd Ctrl+S} (Windows)")
```
**Rendering:**
- Typically in keyboard key style
- May show as boxed or distinct formatting
### .key
Alternative to `.kbd` for key names:
```r
cli_text("Press the {.key RETURN} key")
cli_text("Hold {.key SHIFT} while clicking")
```
### .or
Logical OR separator for alternatives:
```r
cli_text("Use {.val 'yes'} {.or} {.val 'no'}")
cli_abort("Type must be {.val 'auto'} {.or} {.val 'manual'}")
```
**Rendering:**
- Formats as " or " with appropriate styling
- Maintains class formatting for surrounding elements
### .pkg
Package names:
```r
cli_text("Install {.pkg dplyr} for data manipulation")
cli_inform("Loading {.pkg ggplot2}")
cli_abort("{.pkg httr2} is required but not installed")
```
**Features:**
- Distinct package name formatting
- May include CRAN/GitHub links in supported environments
### .dt
Definition term in definition lists:
```r
cli_dl(c(
"{.dt name}" = "User's full name",
"{.dt email}" = "Contact email address"
))
```
**When to use:**
- Definition list terms
- Glossary entries
- Key-value pair keys
### .dd
Definition description in definition lists:
```r
cli_dl(c(
"name" = "{.dd User's full name}",
"email" = "{.dd Contact email address}"
))
```
**When to use:**
- Definition list descriptions
- Glossary definitions
- Key-value pair values
## Vector Collapsing
Vectors are automatically collapsed with appropriate separators:
### Default Behavior
```r
pkgs <- c("dplyr", "tidyr", "ggplot2")
cli_text("Loading packages: {.pkg {pkgs}}")
#> Loading packages: dplyr, tidyr, and ggplot2
files <- c("a.R", "b.R")
cli_text("Modified: {.file {files}}")
#> Modified: a.R and b.R
single <- "data.csv"
cli_text("Found: {.file {single}}")
#> Found: data.csv
```
**Rules:**
- Length 1: no separators
- Length 2: " and " separator
- Length 3+: ", " separators with " and " before last item
### Collapsing Empty Vectors
```r
empty <- character()
cli_text("Files: {.file {empty}}")
#> Files:
cli_text("Files: {?none/one/some}: {.file {empty}}")
#> Files: none:
```
### Custom Collapse Separators
Control collapsing with glue transformers:
```r
items <- c("apple", "banana", "cherry")
# Custom separator
cli_text("Items: {.val {items}}", .transformer = function(text, envir) {
glue::glue_collapse(text, sep = " | ", last = " | ")
})
#> Items: 'apple' | 'banana' | 'cherry'
# OR separator
cli_text("Choose: {.val {items}}", .transformer = function(text, envir) {
glue::glue_collapse(text, sep = ", ", last = " or ")
})
#> Choose: 'apple', 'banana' or 'cherry'
```
### Truncating Long Vectors
```r
many <- letters[1:20]
cli_text("Variables: {.var {many}}")
#> Variables: a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, and t
# Truncate with custom transformer
cli_text("Variables: {.var {head(many, 5)}} and {length(many) - 5} more")
#> Variables: a, b, c, d, e and 15 more
```
## Advanced Patterns
### Nested Markup
Classes can be nested for combined formatting:
```r
cli_text("Call {.fn {.pkg dplyr}::filter} to subset data")
cli_abort("File {.file {.path {dir}}/data.csv} not found")
cli_text("Set {.arg timeout} to {.val {default_timeout}} by default")
```
**Nesting guidelines:**
- Outer class determines primary formatting
- Inner classes add semantic meaning
- Keep nesting depth reasonable (2-3 levels max)
### Combining with Glue Expressions
```r
n <- 5
cli_text("Processing {n} file{?s} from {.path {getwd()}}")
status <- "complete"
cli_inform("Status: {.val {toupper(status)}}")
pkg <- "dplyr"
cli_text("Version: {.pkg {pkg}} {.val {packageVersion(pkg)}}")
```
### Custom Glue Transformers
Full control over formatting with transformers:
```r
# Highlight differences
cli_text(
"Expected {.val {expected}}, got {.val {actual}}",
.transformer = function(text, envir) {
# Custom logic here
text
}
)
# Add prefixes
my_transformer <- function(text, envir) {
if (startsWith(text, ".pkg")) {
paste0("R package: ", glue::glue(text, .envir = envir))
} else {
glue::identity_transformer(text, envir)
}
}
cli_text("Install {.pkg cli}", .transformer = my_transformer)
```
### Conditional Formatting
```r
status <- "error"
cli_text("Status: {.{if(status == 'error') 'strong' else 'emph'} {status}}")
type <- class(x)
cli_text("Type: {if(is.numeric(x)) .val else .cls} {type}")
```
### Multiple Classes on Same Content
Combine semantic classes:
```r
# Package function
cli_text("{.fn {.pkg stats}::median}")
# File in path
cli_text("{.file {.path /usr/local}/script.R}")
# Variable value
cli_text("{.var x} = {.val {x}}")
```
### Working with Lists
```r
config <- list(host = "localhost", port = 8080, ssl = TRUE)
cli_dl(c(
"{.field host}" = "{.val {config$host}}",
"{.field port}" = "{.val {config$port}}",
"{.field ssl}" = "{.val {config$ssl}}"
))
```
### Escaping Markup
Prevent interpretation with double braces:
```r
cli_text("In glue, use {{variable}} syntax")
#> In glue, use {variable} syntax
cli_text("Literal: {{.code not_markup}}")
#> Literal: {.code not_markup}
```
## Pluralization
Pluralization adapts text based on quantities using `{?}` syntax.
### Single Alternative Pattern
Add "s" for plural:
```r
n <- 1
cli_text("{n} file{?s} found")
#> 1 file found
n <- 5
cli_text("{n} file{?s} found")
#> 5 files found
```
### Two Alternative Pattern
Specify singular/plural forms:
```r
n <- 1
cli_text("{n} director{?y/ies}")
#> 1 directory
n <- 3
cli_text("{n} director{?y/ies}")
#> 3 directories
```
**Common patterns:**
- `{?y/ies}` - directory/directories
- `{?/s}` - item/items
- `{?is/are}` - is/are
- `{?/es}` - box/boxes
- `{?ex/ices}` - index/indices
### Three Alternative Pattern
Handle zero/one/many:
```r
n <- 0
cli_text("{?No/One/Some} file{?s} {?is/is/are} ready")
#> No files are ready
n <- 1
cli_text("{?No/One/Some} file{?s} {?is/is/are} ready")
#> One file is ready
n <- 5
cli_text("{?No/One/Some} file{?s} {?is/is/are} ready")
#> Some files are ready
```
### Setting Quantity with qty()
Control pluralization explicitly:
```r
updated <- 3
total <- 10
cli_text("{updated}/{total} {qty(updated)} file{?s} {?needs/need} update{?s}")
#> 3/10 files need updates
```
**When to use qty():**
- When quantity appears elsewhere
- Complex expressions with multiple numbers
- Explicit pluralization control
### no() Helper
Display "no" instead of 0:
```r
n <- 0
cli_text("Found {no(n)} error{?s}")
#> Found no errors
n <- 3
cli_text("Found {no(n)} error{?s}")
#> Found 3 errors
```
### Advanced Pluralization Patterns
**Multiple quantities in one message:**
```r
nerr <- 2
nwarn <- 1
cli_text(
"{nerr} error{?s} and {nwarn} {qty(nwarn)} warning{?s} found"
)
#> 2 errors and 1 warning found
```
**Conditional articles:**
```r
n <- 1
cli_text("Found {?a /}{n} file{?s}")
#> Found a 1 file
n <- 5
cli_text("Found {?a /}{n} file{?s}")
#> Found 5 files
```
**Complex pluralization:**
```r
nfile <- 3
ndir <- 1
cli_text(
"{nfile} file{?s} in {ndir} {qty(ndir)} director{?y/ies}"
)
#> 3 files in 1 directory
```
**Verb agreement:**
```r
n <- 1
cli_text("File {?was/were} modified")
#> File was modified
n <- 3
cli_text("Files {?was/were} modified")
#> Files were modified
```
**Possessives:**
```r
n <- 1
cli_text("User{?'s/'s'} setting{?s}")
#> User's setting
n <- 3
cli_text("Users{?'s/'s'} settings")
#> Users' settings
```
## Performance Considerations
### High-Frequency Messages
For loops with many iterations:
```r
# Expensive - creates cli context each iteration
for (i in 1:10000) {
cli_text("Processing {.val {i}}")
}
# Better - batch messages
if (i %% 1000 == 0) {
cli_text("Processed {.val {i}} items")
}
# Best - use progress bar
cli_progress_bar("Processing", total = 10000)
for (i in 1:10000) {
# work here
cli_progress_update()
}
```
### Expensive Interpolation
Avoid expensive computations in markup:
```r
# Expensive - computes every time
cli_text("Processing {.file {slow_path_computation()}}")
# Better - compute once
path <- slow_path_computation()
cli_text("Processing {.file {path}}")
```
### Conditional Messages
Use conditions to avoid unnecessary formatting:
```r
# Inefficient
if (verbose) cli_text("Status: {.val {expensive_status_check()}}")
# Better
if (verbose) {
status <- expensive_status_check()
cli_text("Status: {.val {status}}")
}
```
### Large Vectors
Truncate large vectors before formatting:
```r
# Problematic with huge vectors
vars <- names(huge_dataframe)
cli_text("Variables: {.var {vars}}")
# Better
n_vars <- length(vars)
if (n_vars > 10) {
cli_text("Variables: {.var {head(vars, 10)}} and {n_vars - 10} more")
} else {
cli_text("Variables: {.var {vars}}")
}
```
## Quick Reference Table
| Class | Use For | Example | Output |
|-------|---------|---------|--------|
| `.code` | Code expressions | `{.code sum(x)}` | `sum(x)` |
| `.fn`, `.fun` | Functions | `{.fn mean}` | `mean()` |
| `.arg` | Function arguments | `{.arg na.rm}` | `na.rm` |
| `.cls` | Class names | `{.cls data.frame}` | data.frame |
| `.type` | Base types | `{.type integer}` | integer |
| `.obj_type_friendly` | Friendly types | `{.obj_type_friendly {x}}` | an integer vector |
| `.file` | File names | `{.file script.R}` | script.R |
| `.path` | Directory paths | `{.path /usr/local}` | /usr/local |
| `.email` | Email addresses | `{.email user@example.com}` | user@example.com |
| `.url` | Web URLs | `{.url https://example.com}` | https://example.com |
| `.href` | Custom links | `{.href [text](url)}` | text (linked) |
| `.val` | Data values | `{.val {x}}` | 42 or 'text' |
| `.var` | Variable names | `{.var column}` | column |
| `.envvar` | Environment vars | `{.envvar PATH}` | PATH |
| `.field` | Object fields | `{.field name}` | name |
| `.str` | String literals | `{.str 'pattern'}` | 'pattern' |
| `.emph` | Emphasis | `{.emph important}` | *important* |
| `.strong` | Strong emphasis | `{.strong critical}` | **critical** |
| `.help` | Help topics | `{.help stats::lm}` | stats::lm (linked) |
| `.topic` | Topic references | `{.topic 'Intro'}` | 'Intro' |
| `.vignette` | Vignettes | `{.vignette pkg::name}` | pkg::name (linked) |
| `.run` | Runnable code | `{.run code}` | code (executable) |
| `.kbd`, `.key` | Keyboard keys | `{.kbd Ctrl+C}` | Ctrl+C |
| `.or` | Logical OR | `{.val x} {.or} {.val y}` | x or y |
| `.pkg` | Package names | `{.pkg dplyr}` | dplyr |
| `.dt` | Definition term | `{.dt term}` | term (in definition list) |
| `.dd` | Definition desc | `{.dd description}` | description (in definition list) |
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.