climenu provides interactive command-line menus,
inspired by popular CLI tools like inquirer.js,
Python’s pick, and Go’s survey. It offers an
intuitive interface for users to make selections directly in the R
console, making your scripts and packages more interactive and
user-friendly.
You can pre-select items by value or by index:
# Pre-select by value
selected <- checkbox(
choices = c("Option A", "Option B", "Option C", "Option D"),
selected = c("Option A", "Option C"),
prompt = "Modify your selection:"
)
# Options A and C will be checked initially# Pre-select by index
selected <- checkbox(
choices = c("Option A", "Option B", "Option C", "Option D"),
selected = c(1, 3), # First and third items
prompt = "Modify your selection:"
)For single-selection menus, pre-selection sets the cursor position:
Sometimes you need the position of the selected item rather than its value:
# Single selection - returns integer
index <- select(
choices = c("First", "Second", "Third"),
return_index = TRUE
)
# Returns: 2 (if user selected "Second")
# Multiple selection - returns integer vector
indices <- checkbox(
choices = c("Alpha", "Beta", "Gamma", "Delta"),
return_index = TRUE
)
# Returns: c(1, 3, 4) (if user selected Alpha, Gamma, Delta)This is particularly useful when you need to map selections back to data structures or when the choice labels differ from the underlying values you want to work with.
For checkbox menus with many options, you can add a “Select all” toggle at the top of the list:
# Enable the "Select all" option
methods <- checkbox(
choices = c("method_a", "method_b", "method_c", "method_d"),
allow_select_all = TRUE,
prompt = "Select methods to run:"
)
# The first item in the menu will be "Select all" / "Deselect all"
# It toggles all items at once and is never included in the resultThis is handy when users are likely to want most or all items and only need to deselect a few.
| Key | Action |
|---|---|
| ↑ or k | Move cursor up |
| ↓ or j | Move cursor down |
| Space | Toggle selection (checkbox only) |
| Enter | Confirm selection |
| Esc or q | Cancel (returns NULL) |
On terminals that don’t support single-key input (e.g. RStudio or
RGui on Windows), climenu falls back to a numbered-prompt
mode — type the number of your choice (or comma-separated numbers for
checkboxes) and press Enter.
# Ask user to configure application settings
cat("\n=== Application Configuration ===\n")
# Choose environment
env <- select(
choices = c("Development", "Staging", "Production"),
prompt = "Select environment:"
)
# Enable features
features <- checkbox(
choices = c("Logging", "Caching", "Analytics", "Debug Mode"),
selected = c("Logging", "Caching"), # Sensible defaults
prompt = "Enable features:"
)
# Choose log level
log_level <- select(
choices = c("ERROR", "WARN", "INFO", "DEBUG", "TRACE"),
selected = "INFO",
prompt = "Select log level:"
)
# Build configuration
config <- list(
environment = env,
features = features,
log_level = log_level
)
cat("\nConfiguration complete!\n")
print(config)# Select datasets to process
available_datasets <- c(
"sales_2023.csv",
"sales_2024.csv",
"customers.csv",
"products.csv",
"inventory.csv"
)
datasets <- checkbox(
choices = available_datasets,
prompt = "Select datasets to process:"
)
if (is.null(datasets)) {
cat("Processing cancelled.\n")
} else {
# Choose processing method
method <- select(
choices = c("Fast (approximate)", "Standard", "Thorough (slow)"),
prompt = "Select processing method:"
)
cat("\nProcessing", length(datasets), "datasets using", method, "method...\n")
# ... processing logic here ...
}# Get list of files
files <- list.files(pattern = "\\.csv$")
if (length(files) == 0) {
cat("No CSV files found.\n")
} else {
# Let user select files, get indices
indices <- checkbox(
choices = files,
return_index = TRUE,
prompt = "Select files to delete:"
)
if (!is.null(indices) && length(indices) > 0) {
files_to_delete <- files[indices]
# Confirm deletion
confirm <- select(
choices = c("Yes, delete them", "No, cancel"),
prompt = paste("Delete", length(files_to_delete), "file(s)?")
)
if (confirm == "Yes, delete them") {
file.remove(files_to_delete)
cat("Deleted", length(files_to_delete), "file(s).\n")
}
}
}When a user cancels a selection (by pressing Esc or q), the menu
functions return NULL:
choice <- select(c("Continue", "Skip", "Abort"))
if (is.null(choice)) {
cat("User cancelled the operation.\n")
# Handle cancellation appropriately
stop("Operation cancelled by user")
}
# Safe to proceed with choice
cat("User selected:", choice, "\n")Always check for NULL returns when user input is
critical to your workflow.
When climenu detects it’s not running in an interactive
session (e.g., in Rscript, automated testing, or R CMD check), it:
select(): returns the first choice (or pre-selected
item if specified)checkbox(): returns pre-selected items (or empty vector
if none)This ensures your code can run in both interactive and automated contexts.
If you’re building an R package and want to use
climenu:
Add climenu to your Imports:
Imports:
climenu
#' Interactive configuration function
#' @export
configure_analysis <- function() {
# Check if interactive
if (!interactive()) {
cli::cli_inform("Using default configuration (non-interactive mode)")
return(get_default_config())
}
# Show interactive menu
method <- climenu::select(
choices = c("Linear Model", "Random Forest", "Neural Network"),
prompt = "Select analysis method:"
)
if (is.null(method)) {
cli::cli_abort("Configuration cancelled by user")
}
# ... rest of configuration logic ...
return(config)
}Keep choices concise - Long choice text may not display well in narrow terminals
Provide clear prompts - Tell users what they’re selecting and what will happen
Use pre-selection wisely - Pre-select sensible defaults to improve UX
Handle cancellation - Always check for
NULL returns
Test non-interactive behavior - Ensure your code works in automated contexts
Consider sort order - Present choices in a logical order (alphabetical, by frequency, by importance)
select(choices, prompt, selected, return_index, max_visible)Single selection menu. Same parameters as menu()
(without type), plus:
max_visible: Maximum items to display at once (default:
10). Set to NULL to show all.checkbox(choices, prompt, selected, return_index, max_visible, allow_select_all)Multiple selection menu. Same parameters as menu()
(without type), plus:
max_visible: Maximum items to display at once (default:
10). Set to NULL to show all.allow_select_all: Add a “Select all” / “Deselect all”
toggle at the top (default: FALSE).Single-key input requires a real terminal (e.g. macOS Terminal,
iTerm2, Linux terminals, Windows Terminal, Rterm). In RStudio or RGui on
Windows, keypress::keypress() is not supported —
climenu detects this automatically and switches to the
numbered-prompt fallback described above. Run from a supported terminal
if you want live arrow-key navigation.
interactive()
returns FALSE)climenu makes it easy to add interactive menus to your R
scripts and packages. Whether you’re building a data analysis wizard,
configuration tool, or just need better user input, climenu
provides an intuitive and robust solution.
Happy menu-making!