Imported from inspercidades/insperplot (
AGENTS.md). Install upstream withnpx skills add inspercidades/insperplot. Copyright stays with the author.
AGENTS.md
This file provides guidance to Codex (Codex.ai/code) when working with code in this repository.
Package Overview
insperplot is an R package that extends ggplot2 with Insper Instituto de Ensino e Pesquisa's visual identity. It provides custom themes, color palettes, scales, and specialized plotting functions for academic and institutional use.
Common Development Commands
Testing
# Run all tests
Rscript -e "devtools::test()"
# Run tests with coverage report
Rscript -e "covr::package_coverage()"
# Run specific test file
Rscript -e "testthat::test_file('tests/testthat/test-theme.R')"
# Check visual regression tests
Rscript -e "devtools::test(filter = 'visual')"
Building and Checking
# Full R CMD check (must pass with 0 errors, 0 warnings, 0 notes)
Rscript -e "devtools::check()"
# Build package documentation
Rscript -e "devtools::document()"
# Build pkgdown site
Rscript -e "pkgdown::build_site()"
# Install development version locally
Rscript -e "devtools::install()"
Code Quality
# Check for code style issues
Rscript -e "lintr::lint_package()"
# Auto-format code (if styler is used)
Rscript -e "styler::style_pkg()"
Architecture and Code Organization
Core Philosophy
This package follows modern R development best practices (2025 standards):
- Native pipe
|>throughout (NOT magrittr%>%) - Modern tidyverse patterns (dplyr 1.1+ with
.by,reframe(),pick()) - Modern rlang patterns (embrace
{{}}, injection!!, splicing!!!) - Bundled fonts via
systemfonts::register_font()in.onLoad()(NOT showtext/extrafont due to DPI conflicts)
Key R Files Structure
R/theme_insper.R—theme_insper()and internaldetect_font()(theme variants live here, not a separate file)R/plot-<name>.R— one file per exported plot function (plot-area.R,plot-barplot.R,plot-boxplot.R,plot-density.R,plot-heatmap.R,plot-histogram.R,plot-scatterplot.R,plot-timeseries.R,plot-violin.R). Add new plots as a new file in this pattern.R/palette-utils.R— exportedinsper_palette(),show_insper_palettes(), and internalget_insper_colors(),palette_metadata()R/insper_palette.R— internalinsper_pal()helper used by scalesR/scales.R—scale_color_insper_{c,d}()/scale_fill_insper_{c,d}()(+colouraliases)R/utils.R—save_insper_plot(),format_num_br(), plus internal helpers:detect_aesthetic_type(),warn_palette_ignored(),calculate_luminance(),get_contrast_text_color(),has_insper_fonts(),is_valid_color()R/data.R— dataset documentation; data lives indata/andR/sysdata.rdaR/zzz.R—.onLoad()registers the bundled Inter font viasystemfonts::register_font()R/globals.R—utils::globalVariables()declarations
Development Guidelines
Full coding standards are documented in
claude/coding_guidelines.mdandclaude/modern-error-handling-in-r.md. The rules below are the package-critical highlights; consult those files for complete guidance.
Code Style (see claude/coding_guidelines.md)
- Always use native pipe
|>- NEVER use%>% - Use modern dplyr patterns:
.byfor grouping (notgroup_by() |> ... |> ungroup()) - Use rlang correctly:
{{}}(embrace) for forwarding function arguments!!for single injection,!!!for splicing.data[[]]for programmatic column access
- Use cli package for messages:
cli::cli_abort(),cli::cli_warn(),cli::cli_alert_*() - Snake_case for everything except S3 methods
- Type-stable outputs: prefer
map_dbl()oversapply() - Join syntax: use
join_by()notc("a" = "b")character vectors - Pipe chains: max 5–7 steps; break longer chains into named intermediate objects
Error Handling (see claude/modern-error-handling-in-r.md)
- Default: use
rlang::try_fetch()instead oftryCatch()— preserves call stack forrlang::last_trace() - Error chaining: wrap low-level errors with
rlang::abort(..., parent = cnd)to attach context without losing the original trace - Mapping: use
purrr::possibly()(skip failures, return default) orpurrr::safely()(keep both result and error) when iterating over vectors - Cleanup: keep
on.exit()ortryCatch(..., finally = ...)for resource cleanup —try_fetch()has nofinally - Warnings without stopping: keep
withCallingHandlers()to record warnings while letting execution continue - Avoid:
try()+inherits(result, "try-error"), nestedtryCatch, andpaste("Context:", e$message)for wrapping
Testing Requirements
- All new functions must have tests in
tests/testthat/test-*.R - Aim for >80% code coverage
- Use
vdiffrfor visual regression tests of plots - Test both happy path and error conditions
- Font tests use helper in
tests/testthat/helper-fonts.R
Documentation Requirements
- All exported functions must have roxygen2 documentation
- Include
@familytag (themes, colors, scales, plots, utilities) - Include
@exampleswith all exported functions. Use@examplesIf has_insper_fonts()for examples that render plots with custom fonts (guards against non-interactive CMD check). Use\dontrun{}for examples with side effects. - Use
@paramwith<[data-masked]>for rlang functions - Include
@seealsocross-references
When making breaking changes:
- Deprecate in one release (show warnings, update NEWS.md)
- Remove in next release
- Provide clear migration guide in NEWS.md
- Update all examples, tests, vignettes, README
Package Data Management
Creating/Updating Datasets
# Run dataset creation scripts (they save to data/)
Rscript data-raw/datasets.R
# Document datasets in R/data.R with full roxygen2
# Include: @format, @source, @details, @examples, @seealso
Logo and Visual Assets
# Regenerate package logo
Rscript data-raw/create_logo.R
# Creates man/figures/logo.png
# Uses hexSticker, theme_insper(), and Insper colors
Color Palette Definition
# Color palettes defined in data-raw/colors_palettes.R
# Creates R/sysdata.rda with insper_colors list
# Updates should maintain backward compatibility with old names
Common Workflows
Adding a New Color Palette
- Edit
data-raw/colors_palettes.Rto add palette definition - Run
Rscript data-raw/colors_palettes.Rto regenerateR/sysdata.rda - Update
insper_palette()documentation with new palette name - Add tests in
tests/testthat/test-colors.R - Update
show_insper_palettes()to support new palette (if special handling needed)
Adding a New Plot Function
- Create a new file
R/plot-<name>.R(one plot function per file — see existingplot-barplot.R,plot-scatterplot.R, etc.) - Use
rlang::enquo()+rlang::quo_is_null()for optional aesthetics - Apply
theme_insper()as final layer - Add roxygen2 documentation with
@family plots - Add tests in
tests/testthat/test-plots.R(andtest-smart-detection.Rif the function usesdetect_aesthetic_type()) - Add visual regression tests in
tests/testthat/test-visual.R - Update
_pkgdown.ymlto include in "Plot Functions" section
Adding a New Theme Variant
- Add the function in
R/theme_insper.R(theme variants live alongside the base theme — there is no separatetheme_variants.R) - Build on
theme_insper()using%+replace%operator - Follow font detection pattern with
detect_font() - Add comprehensive parameter validation
- Add tests in
tests/testthat/test-theme.R - Update
_pkgdown.ymlto include in "Themes" section
Important Constraints and Gotchas
Bundled Fonts (inst/fonts/)
- Inter is shipped as TTF files in
inst/fonts/inter/(OFL-licensed) - Registered automatically in
.onLoad()viasystemfonts::register_font()— no user action needed detect_font()checks bothregistry_fonts()(bundled) andsystem_fonts()(system-installed)- Georgia (title font) is NOT bundled — it's a system font pre-installed on most OSes;
serifis the fallback - To refresh or update fonts, run
data-raw/download_fonts.R
ggplot2 Integration
- All plot functions return ggplot objects (composable with
+) - Don't capture user's ggplot2 calls - let them add layers
- Theme functions use
%+replace%not+to avoid accumulation - Use
ggplot2::prefix for all ggplot2 functions in package code
rlang and Data Masking
- Plot functions accept both bare names and tidy-eval expressions
- Use
rlang::enquo()to capture,rlang::quo_is_null()to check - Use
{{}}when passing to dplyr/ggplot2 functions - Never use string parsing or
eval(parse())patterns
Brazilian Localization
- Formatter functions default to Brazilian conventions (comma decimal, period thousands)
- Caption function defaults to Portuguese (
lang = "pt") - Consider adding English alternatives when appropriate
Package Load Behavior (R/zzz.R)
.onLoad()registers the bundled Inter family viasystemfonts::register_font(); skips it if already present as a system font to avoid conflicts
Smart Aesthetic Detection (R/utils.R)
- Plot functions that accept a
color/fillargument calldetect_aesthetic_type()to distinguish a mapped variable from a constant color string - When a user passes a constant color but also a palette,
warn_palette_ignored()emits acli::cli_warn()so the palette isn't silently dropped - Use these helpers in any new plot function that takes optional color aesthetics
Contrast-Aware Text on Bars (R/utils.R)
calculate_luminance()+get_contrast_text_color()pick white or dark text per-bar based on fill luminance- Used by
insper_barplot()for stacked/filled variants; reuse for any plot that overlays text labels on colored shapes
pkgdown Website Structure
The package website (_pkgdown.yml) organizes functions into categories:
- Themes: Theme functions
- Colors and Palettes: Color access and palette functions
- ggplot2 Scales: Scale functions for continuous/discrete data
- Plot Functions: High-level plotting functions
- Utilities: Formatters, caption builder, save function
- Data: Package datasets
Website uses Insper colors in theme (primary: #E4002B, secondary: #009491).