From f50f8deeffc7758c6332fc9ed6a45f58c49808bf Mon Sep 17 00:00:00 2001 From: Jenny Bryan Date: Fri, 27 Feb 2026 14:23:14 -0800 Subject: [PATCH 1/3] Add use_readme_qmd() --- NAMESPACE | 1 + NEWS.md | 2 + R/badge.R | 8 +- R/readme.R | 87 +++++++++++--- R/release.R | 3 +- R/tidyverse.R | 2 +- R/upkeep.R | 8 +- inst/templates/package-README-qmd | 71 ++++++++++++ inst/templates/project-README-qmd | 41 +++++++ inst/templates/readme-rmd-pre-commit.sh | 8 +- man/badges.Rd | 4 +- man/use_readme_rmd.Rd | 33 +++--- tests/testthat/_snaps/badge.md | 9 +- tests/testthat/_snaps/coverage.md | 3 +- tests/testthat/_snaps/readme.md | 148 ++++++++++++++++++++++++ tests/testthat/_snaps/upkeep.md | 6 +- tests/testthat/test-readme.R | 49 ++++++++ 17 files changed, 436 insertions(+), 47 deletions(-) create mode 100644 inst/templates/package-README-qmd create mode 100644 inst/templates/project-README-qmd diff --git a/NAMESPACE b/NAMESPACE index 3ec8b6f4b..2663acdaa 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -159,6 +159,7 @@ export(use_rcpp) export(use_rcpp_armadillo) export(use_rcpp_eigen) export(use_readme_md) +export(use_readme_qmd) export(use_readme_rmd) export(use_release_issue) export(use_reprex) diff --git a/NEWS.md b/NEWS.md index 7331c9d3a..39437a9d8 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # usethis (development version) +* `use_readme_qmd()` creates a starter `README.qmd` with Quarto-flavored YAML frontmatter, analogous to `use_readme_rmd()` (#1671). Thanks @VisruthSK for getting the ball rolling. + * `use_pipe()` is now deprecated (@math-mcshane, #2124). * `use_claude_code()` is an experimental helper to set up Claude code in an R package in the same way as the tidyverse team (#2195). diff --git a/R/badge.R b/R/badge.R index 7dcf84464..d6df11898 100644 --- a/R/badge.R +++ b/R/badge.R @@ -5,8 +5,8 @@ #' and link out to relevant external resources. To allow badges to be added #' automatically, ensure your badge block starts with a line containing only #' `` and ends with a line containing only -#' ``. The templates used by [use_readme_md()] and -#' [use_readme_rmd()] include this block. +#' ``. The templates used by [use_readme_rmd()], +#' [use_readme_qmd()], and [use_readme_md()] and include this block. #' #' @details #' @@ -53,7 +53,7 @@ use_badge <- function(badge_name, href, src) { if (is.null(path)) { ui_bullets(c( "!" = "Can't find a README for the current project.", - "i" = "See {.fun usethis::use_readme_rmd} for help creating this file.", + "i" = "See {.fun usethis::use_readme_rmd} or {.fun usethis::use_readme_rmd} for help creating this file.", "i" = "Badge link will only be printed to screen." )) path <- "README" @@ -224,5 +224,5 @@ badge_start <- "" badge_end <- "" find_readme <- function() { - path_first_existing(proj_path(c("README.Rmd", "README.md"))) + path_first_existing(proj_path(c("README.Rmd", "README.qmd", "README.md"))) } diff --git a/R/readme.R b/R/readme.R index cf1a3651c..7788c9c4a 100644 --- a/R/readme.R +++ b/R/readme.R @@ -6,22 +6,25 @@ #' * R code to install from GitHub, if GitHub usage detected #' * a basic example #' -#' Use `Rmd` if you want a rich intermingling of code and output. Use `md` for a -#' basic README. `README.Rmd` will be automatically added to `.Rbuildignore`. -#' The resulting README is populated with default YAML frontmatter and R fenced -#' code blocks (`md`) or chunks (`Rmd`). +#' Use `Rmd` or `qmd` if you want a rich intermingling of code and output. +#' Use `md` for a basic README. `README.Rmd` and `README.qmd` will be +#' automatically added to `.Rbuildignore`. The resulting README is populated +#' with default YAML frontmatter and R fenced code blocks (`md`) or +#' chunks (`Rmd`, `qmd`). #' -#' If you use `Rmd`, you'll still need to render it regularly, to keep -#' `README.md` up-to-date. `devtools::build_readme()` is handy for this. You -#' could also use GitHub Actions to re-render `README.Rmd` every time you push. -#' An example workflow can be found in the `examples/` directory here: +#' If you use `Rmd` or `qmd`, you'll still need to render it regularly, to +#' keep `README.md` up-to-date. `devtools::build_readme()` is handy for +#' this. You could also use GitHub Actions to re-render `README.Rmd` or +#' `README.qmd` every time you push. An example workflow can be found in +#' the `examples/` directory here: #' . #' -#' If the current project is a Git repo, then `use_readme_rmd()` automatically -#' configures a pre-commit hook that helps keep `README.Rmd` and `README.md`, -#' synchronized. The hook creates friction if you try to commit when -#' `README.Rmd` has been edited more recently than `README.md`. If this hook -#' causes more problems than it solves for you, it is implemented in +#' If the current project is a Git repo, then `use_readme_rmd()` and +#' `use_readme_qmd()` automatically configure a pre-commit hook that helps +#' keep `README.md` synchronized with the source file. The hook creates +#' friction if you try to commit when `README.Rmd` or `README.qmd` has +#' been edited more recently than `README.md`. If this hook causes more +#' problems than it solves for you, it is implemented in #' `.git/hooks/pre-commit`, which you can modify or even delete. #' #' @inheritParams use_template @@ -32,6 +35,7 @@ #' @examples #' \dontrun{ #' use_readme_rmd() +#' use_readme_qmd() #' use_readme_md() #' } use_readme_rmd <- function(open = rlang::is_interactive()) { @@ -65,6 +69,63 @@ use_readme_rmd <- function(open = rlang::is_interactive()) { )) } + ui_bullets(c( + "_" = "Use {.fun devtools::build_readme} to render {.path {pth('README.Rmd')}}." + )) + + if (uses_git()) { + use_git_hook( + "pre-commit", + render_template("readme-rmd-pre-commit.sh") + ) + } + + invisible(TRUE) +} + +#' @export +#' @rdname use_readme_rmd +use_readme_qmd <- function(open = rlang::is_interactive()) { + check_is_project() + + is_pkg <- is_package() + repo_spec <- tryCatch(target_repo_spec(ask = FALSE), error = function(e) NULL) + nm <- if (is_pkg) "Package" else "Project" + data <- list2( + !!nm := project_name(), + on_github = !is.null(repo_spec), + github_spec = repo_spec + ) + + new <- use_template( + if (is_pkg) "package-README-qmd" else "project-README-qmd", + "README.qmd", + data = data, + ignore = is_pkg, + open = open + ) + if (!new) { + return(invisible(FALSE)) + } + + if (is_pkg && !data$on_github) { + ui_bullets(c( + "_" = "Update {.path {pth('README.qmd')}} to include installation instructions." + )) + } + + if (file_exists(proj_path("README.Rmd"))) { + ui_bullets(c( + "!" = "A pre-existing {.path {pth('README.Rmd')}} was found.", + "_" = "Migrate its content to {.path {pth('README.qmd')}}.", + "_" = "Delete {.path {pth('README.Rmd')}} when the migration is done." + )) + } + + ui_bullets(c( + "_" = "Use {.fun devtools::build_readme} to render {.path {pth('README.qmd')}}." + )) + if (uses_git()) { use_git_hook( "pre-commit", diff --git a/R/release.R b/R/release.R index 89722e90e..e56f3154f 100644 --- a/R/release.R +++ b/R/release.R @@ -75,7 +75,8 @@ release_checklist <- function(version, on_cran, target_repo = NULL) { has_news <- file_exists(proj_path("NEWS.md")) has_pkgdown <- uses_pkgdown() has_lifecycle <- proj_desc()$has_dep("lifecycle") - has_readme <- file_exists(proj_path("README.Rmd")) + has_readme <- file_exists(proj_path("README.Rmd")) || + file_exists(proj_path("README.qmd")) has_github_links <- has_github_links(target_repo) is_posit_pkg <- is_posit_pkg() milestone_num <- gh_milestone_number(target_repo, version) diff --git a/R/tidyverse.R b/R/tidyverse.R index b75429cf4..910a6b47f 100644 --- a/R/tidyverse.R +++ b/R/tidyverse.R @@ -66,7 +66,7 @@ create_tidy_package <- function(path, copyright_holder = NULL) { use_mit_license(copyright_holder) use_tidy_description() - use_readme_rmd(open = FALSE) + use_readme_qmd(open = FALSE) use_lifecycle_badge("experimental") use_cran_badge() diff --git a/R/upkeep.R b/R/upkeep.R index 0beb7485a..3d083dd42 100644 --- a/R/upkeep.R +++ b/R/upkeep.R @@ -62,7 +62,11 @@ upkeep_checklist <- function(target_repo = NULL) { has_github_links <- has_github_links(target_repo) bullets <- c( - todo("`usethis::use_readme_rmd()`", !file_exists(proj_path("README.Rmd"))), + todo( + "`usethis::use_readme_rmd()` or `usethis::use_readme_qmd()`", + !file_exists(proj_path("README.Rmd")) && + !file_exists(proj_path("README.qmd")) + ), todo("`usethis::use_roxygen_md()`", !is_true(uses_roxygen_md())), todo("`usethis::use_github_links()`", !has_github_links), todo("`usethis::use_pkgdown_github_pages()`", !uses_pkgdown()), @@ -161,7 +165,7 @@ tidy_upkeep_checklist <- function( bullets, "### Pre-history", "", - todo("`usethis::use_readme_rmd()`"), + todo("`usethis::use_readme_rmd()` or `usethis::use_readme_qmd()`"), todo("`usethis::use_roxygen_md()`"), todo("`usethis::use_github_links()`"), todo("`usethis::use_pkgdown_github_pages()`"), diff --git a/inst/templates/package-README-qmd b/inst/templates/package-README-qmd new file mode 100644 index 000000000..2c1c08955 --- /dev/null +++ b/inst/templates/package-README-qmd @@ -0,0 +1,71 @@ +--- +format: + gfm: + default-image-extension: "" +--- + + + +```{r} +#| include: false +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + fig.path = "man/figures/README-", + out.width = "100%" +) +``` + +# {{{ Package }}} + + + + +The goal of {{{ Package }}} is to ... + +## Installation + +{{#on_github}} +You can install the development version of {{{ Package }}} from [GitHub](https://github.com/) with: + +``` r +# install.packages("pak") +pak::pak("{{{ github_spec }}}") +``` +{{/on_github}} +{{^on_github}} +You can install the development version of {{{ Package }}} like so: + +``` r +# FILL THIS IN! HOW CAN PEOPLE INSTALL YOUR DEV PACKAGE? +``` +{{/on_github}} + +## Example + +This is a basic example which shows you how to solve a common problem: + +```{r} +#| label: example +library({{Package}}) +## basic example code +``` + +What is special about using `README.qmd` instead of just `README.md`? You can include R chunks like so: + +```{r} +#| label: cars +summary(cars) +``` + +You'll still need to render `README.qmd` regularly, to keep `README.md` up-to-date. `devtools::build_readme()` is handy for this. + +You can also embed plots, for example: + +```{r} +#| label: pressure +#| echo: false +plot(pressure) +``` + +In that case, don't forget to commit and push the resulting figure files, so they display on GitHub and CRAN. diff --git a/inst/templates/project-README-qmd b/inst/templates/project-README-qmd new file mode 100644 index 000000000..0fdf6677f --- /dev/null +++ b/inst/templates/project-README-qmd @@ -0,0 +1,41 @@ +--- +format: + gfm: + default-image-extension: "" +--- + + + +```{r} +#| include: false +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +# {{{ Project }}} + + + + +The goal of {{{ Project }}} is to ... + +What is special about using `README.qmd` instead of just `README.md`? You can include R chunks like so: + +```{r} +#| label: cars +summary(cars) +``` + +You'll still need to render `README.qmd` regularly, to keep `README.md` up-to-date. + +You can also embed plots, for example: + +```{r} +#| label: pressure +#| echo: false +plot(pressure) +``` + +In that case, don't forget to commit and push the resulting figure files, so they display on GitHub. diff --git a/inst/templates/readme-rmd-pre-commit.sh b/inst/templates/readme-rmd-pre-commit.sh index d56327f36..f8126a51e 100644 --- a/inst/templates/readme-rmd-pre-commit.sh +++ b/inst/templates/readme-rmd-pre-commit.sh @@ -1,15 +1,15 @@ #!/bin/bash -README=($(git diff --cached --name-only | grep -Ei '^README\.[R]?md$')) +README=($(git diff --cached --name-only | grep -Ei '^README\.[qR]?md$')) MSG="use 'git commit --no-verify' to override this check" if [[ ${#README[@]} == 0 ]]; then exit 0 fi -if [[ README.Rmd -nt README.md ]]; then - echo -e "README.md is out of date; please re-knit README.Rmd\n$MSG" +if [[ README.Rmd -nt README.md ]] || [[ README.qmd -nt README.md ]]; then + echo -e "README.md is out of date; please re-render README.Rmd/README.qmd\n$MSG" exit 1 elif [[ ${#README[@]} -lt 2 ]]; then - echo -e "README.Rmd and README.md should be both staged\n$MSG" + echo -e "README.Rmd/README.qmd and README.md should be both staged\n$MSG" exit 1 fi diff --git a/man/badges.Rd b/man/badges.Rd index 8dcafbf09..49bc92634 100644 --- a/man/badges.Rd +++ b/man/badges.Rd @@ -52,8 +52,8 @@ badges that report information, such as the CRAN version or test coverage, and link out to relevant external resources. To allow badges to be added automatically, ensure your badge block starts with a line containing only \verb{} and ends with a line containing only -\verb{}. The templates used by \code{\link[=use_readme_md]{use_readme_md()}} and -\code{\link[=use_readme_rmd]{use_readme_rmd()}} include this block. +\verb{}. The templates used by \code{\link[=use_readme_rmd]{use_readme_rmd()}}, +\code{\link[=use_readme_qmd]{use_readme_qmd()}}, and \code{\link[=use_readme_md]{use_readme_md()}} and include this block. } \details{ \itemize{ diff --git a/man/use_readme_rmd.Rd b/man/use_readme_rmd.Rd index a7d8e0570..6b43d8364 100644 --- a/man/use_readme_rmd.Rd +++ b/man/use_readme_rmd.Rd @@ -2,11 +2,14 @@ % Please edit documentation in R/readme.R \name{use_readme_rmd} \alias{use_readme_rmd} +\alias{use_readme_qmd} \alias{use_readme_md} \title{Create README files} \usage{ use_readme_rmd(open = rlang::is_interactive()) +use_readme_qmd(open = rlang::is_interactive()) + use_readme_md(open = rlang::is_interactive()) } \arguments{ @@ -21,27 +24,31 @@ Creates skeleton README files with possible stubs for \item a basic example } -Use \code{Rmd} if you want a rich intermingling of code and output. Use \code{md} for a -basic README. \code{README.Rmd} will be automatically added to \code{.Rbuildignore}. -The resulting README is populated with default YAML frontmatter and R fenced -code blocks (\code{md}) or chunks (\code{Rmd}). +Use \code{Rmd} or \code{qmd} if you want a rich intermingling of code and output. +Use \code{md} for a basic README. \code{README.Rmd} and \code{README.qmd} will be +automatically added to \code{.Rbuildignore}. The resulting README is populated +with default YAML frontmatter and R fenced code blocks (\code{md}) or +chunks (\code{Rmd}, \code{qmd}). -If you use \code{Rmd}, you'll still need to render it regularly, to keep -\code{README.md} up-to-date. \code{devtools::build_readme()} is handy for this. You -could also use GitHub Actions to re-render \code{README.Rmd} every time you push. -An example workflow can be found in the \verb{examples/} directory here: +If you use \code{Rmd} or \code{qmd}, you'll still need to render it regularly, to +keep \code{README.md} up-to-date. \code{devtools::build_readme()} is handy for +this. You could also use GitHub Actions to re-render \code{README.Rmd} or +\code{README.qmd} every time you push. An example workflow can be found in +the \verb{examples/} directory here: \url{https://github.com/r-lib/actions/}. -If the current project is a Git repo, then \code{use_readme_rmd()} automatically -configures a pre-commit hook that helps keep \code{README.Rmd} and \code{README.md}, -synchronized. The hook creates friction if you try to commit when -\code{README.Rmd} has been edited more recently than \code{README.md}. If this hook -causes more problems than it solves for you, it is implemented in +If the current project is a Git repo, then \code{use_readme_rmd()} and +\code{use_readme_qmd()} automatically configure a pre-commit hook that helps +keep \code{README.md} synchronized with the source file. The hook creates +friction if you try to commit when \code{README.Rmd} or \code{README.qmd} has +been edited more recently than \code{README.md}. If this hook causes more +problems than it solves for you, it is implemented in \code{.git/hooks/pre-commit}, which you can modify or even delete. } \examples{ \dontrun{ use_readme_rmd() +use_readme_qmd() use_readme_md() } } diff --git a/tests/testthat/_snaps/badge.md b/tests/testthat/_snaps/badge.md index 9d249c1b8..12bc5b491 100644 --- a/tests/testthat/_snaps/badge.md +++ b/tests/testthat/_snaps/badge.md @@ -23,7 +23,8 @@ use_r_universe_badge("OWNER_DIRECT/SCRUBBED") Message ! Can't find a README for the current project. - i See `usethis::use_readme_rmd()` for help creating this file. + i See `usethis::use_readme_rmd()` or `usethis::use_readme_rmd()` for help + creating this file. i Badge link will only be printed to screen. [ ] Copy and paste the following lines into 'README': @@ -36,7 +37,8 @@ use_r_universe_badge() Message ! Can't find a README for the current project. - i See `usethis::use_readme_rmd()` for help creating this file. + i See `usethis::use_readme_rmd()` or `usethis::use_readme_rmd()` for help + creating this file. i Badge link will only be printed to screen. [ ] Copy and paste the following lines into 'README': @@ -49,7 +51,8 @@ use_r_universe_badge() Message ! Can't find a README for the current project. - i See `usethis::use_readme_rmd()` for help creating this file. + i See `usethis::use_readme_rmd()` or `usethis::use_readme_rmd()` for help + creating this file. i Badge link will only be printed to screen. [ ] Copy and paste the following lines into 'README': diff --git a/tests/testthat/_snaps/coverage.md b/tests/testthat/_snaps/coverage.md index df963ad75..19ff973ab 100644 --- a/tests/testthat/_snaps/coverage.md +++ b/tests/testthat/_snaps/coverage.md @@ -4,7 +4,8 @@ use_codecov_badge("OWNER/REPO") Message ! Can't find a README for the current project. - i See `usethis::use_readme_rmd()` for help creating this file. + i See `usethis::use_readme_rmd()` or `usethis::use_readme_rmd()` for help + creating this file. i Badge link will only be printed to screen. [ ] Copy and paste the following lines into 'README': diff --git a/tests/testthat/_snaps/readme.md b/tests/testthat/_snaps/readme.md index 631898991..5fcd9e357 100644 --- a/tests/testthat/_snaps/readme.md +++ b/tests/testthat/_snaps/readme.md @@ -182,3 +182,151 @@ In that case, don't forget to commit and push the resulting figure files, so they display on GitHub and CRAN. +# use_readme_qmd() notices a pre-existing README.Rmd + + Code + use_readme_qmd() + Message + v Writing 'README.qmd'. + v Adding "^README\\.qmd$" to '.Rbuildignore'. + [ ] Update 'README.qmd' to include installation instructions. + ! A pre-existing 'README.Rmd' was found. + [ ] Migrate its content to 'README.qmd'. + [ ] Delete 'README.Rmd' when the migration is done. + [ ] Use `devtools::build_readme()` to render 'README.qmd'. + +# use_readme_qmd() has expected form for a non-GitHub package + + Code + writeLines(read_utf8("README.qmd")) + Output + --- + format: + gfm: + default-image-extension: "" + --- + + + + ```{r} + #| include: false + knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + fig.path = "man/figures/README-", + out.width = "100%" + ) + ``` + + # {TESTPKG} + + + + + The goal of {TESTPKG} is to ... + + ## Installation + + You can install the development version of {TESTPKG} like so: + + ``` r + # FILL THIS IN! HOW CAN PEOPLE INSTALL YOUR DEV PACKAGE? + ``` + + ## Example + + This is a basic example which shows you how to solve a common problem: + + ```{r} + #| label: example + library({TESTPKG}) + ## basic example code + ``` + + What is special about using `README.qmd` instead of just `README.md`? You can include R chunks like so: + + ```{r} + #| label: cars + summary(cars) + ``` + + You'll still need to render `README.qmd` regularly, to keep `README.md` up-to-date. `devtools::build_readme()` is handy for this. + + You can also embed plots, for example: + + ```{r} + #| label: pressure + #| echo: false + plot(pressure) + ``` + + In that case, don't forget to commit and push the resulting figure files, so they display on GitHub and CRAN. + +# use_readme_qmd() has expected form for a GitHub package + + Code + writeLines(read_utf8("README.qmd")) + Output + --- + format: + gfm: + default-image-extension: "" + --- + + + + ```{r} + #| include: false + knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>", + fig.path = "man/figures/README-", + out.width = "100%" + ) + ``` + + # {TESTPKG} + + + + + The goal of {TESTPKG} is to ... + + ## Installation + + You can install the development version of {TESTPKG} from [GitHub](https://github.com/) with: + + ``` r + # install.packages("pak") + pak::pak("OWNER/TESTPKG") + ``` + + ## Example + + This is a basic example which shows you how to solve a common problem: + + ```{r} + #| label: example + library({TESTPKG}) + ## basic example code + ``` + + What is special about using `README.qmd` instead of just `README.md`? You can include R chunks like so: + + ```{r} + #| label: cars + summary(cars) + ``` + + You'll still need to render `README.qmd` regularly, to keep `README.md` up-to-date. `devtools::build_readme()` is handy for this. + + You can also embed plots, for example: + + ```{r} + #| label: pressure + #| echo: false + plot(pressure) + ``` + + In that case, don't forget to commit and push the resulting figure files, so they display on GitHub and CRAN. + diff --git a/tests/testthat/_snaps/upkeep.md b/tests/testthat/_snaps/upkeep.md index 33652db98..791e25735 100644 --- a/tests/testthat/_snaps/upkeep.md +++ b/tests/testthat/_snaps/upkeep.md @@ -9,7 +9,7 @@ ### Pre-history - * [ ] `usethis::use_readme_rmd()` + * [ ] `usethis::use_readme_rmd()` or `usethis::use_readme_qmd()` * [ ] `usethis::use_roxygen_md()` * [ ] `usethis::use_github_links()` * [ ] `usethis::use_pkgdown_github_pages()` @@ -122,7 +122,7 @@ Code writeLines(upkeep_checklist()) Output - * [ ] `usethis::use_readme_rmd()` + * [ ] `usethis::use_readme_rmd()` or `usethis::use_readme_qmd()` * [ ] `usethis::use_github_links()` * [ ] `usethis::use_pkgdown_github_pages()` * [ ] `usethis::use_tidy_description()` @@ -144,7 +144,7 @@ Code writeLines(checklist) Output - * [ ] `usethis::use_readme_rmd()` + * [ ] `usethis::use_readme_rmd()` or `usethis::use_readme_qmd()` * [ ] `usethis::use_github_links()` * [ ] `usethis::use_pkgdown_github_pages()` * [ ] `usethis::use_tidy_description()` diff --git a/tests/testthat/test-readme.R b/tests/testthat/test-readme.R index f2c8a0f4d..b28a23025 100644 --- a/tests/testthat/test-readme.R +++ b/tests/testthat/test-readme.R @@ -65,3 +65,52 @@ test_that("use_readme_rmd() has expected form for a GitHub package", { transform = scrub_testpkg ) }) + +test_that("use_readme_qmd() creates README.qmd", { + create_local_package() + use_readme_qmd() + expect_proj_file("README.qmd") +}) + +test_that("use_readme_qmd() sets up git pre-commit hook if pkg uses git", { + skip_if_no_git_user() + + create_local_package() + use_git() + use_readme_qmd(open = FALSE) + expect_proj_file(".git", "hooks", "pre-commit") +}) + +test_that("use_readme_qmd() notices a pre-existing README.Rmd", { + local_interactive(FALSE) + + create_local_package() + use_readme_rmd() + withr::local_options(usethis.quiet = FALSE) + expect_snapshot(use_readme_qmd(), transform = scrub_testpkg) + expect_proj_file("README.qmd") + expect_proj_file("README.Rmd") +}) + +test_that("use_readme_qmd() has expected form for a non-GitHub package", { + local_interactive(FALSE) + + create_local_package() + use_readme_qmd() + expect_snapshot( + writeLines(read_utf8("README.qmd")), + transform = scrub_testpkg + ) +}) + +test_that("use_readme_qmd() has expected form for a GitHub package", { + local_interactive(FALSE) + local_target_repo_spec("OWNER/TESTPKG") + + create_local_package() + use_readme_qmd() + expect_snapshot( + writeLines(read_utf8("README.qmd")), + transform = scrub_testpkg + ) +}) From d9296ed6a17bd224d4bca74740be8be3a3314375 Mon Sep 17 00:00:00 2001 From: Jenny Bryan Date: Fri, 27 Feb 2026 14:37:42 -0800 Subject: [PATCH 2/3] Fix a copy/paste-o --- R/badge.R | 2 +- tests/testthat/_snaps/badge.md | 6 +++--- tests/testthat/_snaps/coverage.md | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/R/badge.R b/R/badge.R index d6df11898..ec5f6cbe1 100644 --- a/R/badge.R +++ b/R/badge.R @@ -53,7 +53,7 @@ use_badge <- function(badge_name, href, src) { if (is.null(path)) { ui_bullets(c( "!" = "Can't find a README for the current project.", - "i" = "See {.fun usethis::use_readme_rmd} or {.fun usethis::use_readme_rmd} for help creating this file.", + "i" = "See {.fun usethis::use_readme_qmd} or {.fun usethis::use_readme_rmd} for help creating this file.", "i" = "Badge link will only be printed to screen." )) path <- "README" diff --git a/tests/testthat/_snaps/badge.md b/tests/testthat/_snaps/badge.md index 12bc5b491..de3eb82a5 100644 --- a/tests/testthat/_snaps/badge.md +++ b/tests/testthat/_snaps/badge.md @@ -23,7 +23,7 @@ use_r_universe_badge("OWNER_DIRECT/SCRUBBED") Message ! Can't find a README for the current project. - i See `usethis::use_readme_rmd()` or `usethis::use_readme_rmd()` for help + i See `usethis::use_readme_qmd()` or `usethis::use_readme_rmd()` for help creating this file. i Badge link will only be printed to screen. [ ] Copy and paste the following lines into 'README': @@ -37,7 +37,7 @@ use_r_universe_badge() Message ! Can't find a README for the current project. - i See `usethis::use_readme_rmd()` or `usethis::use_readme_rmd()` for help + i See `usethis::use_readme_qmd()` or `usethis::use_readme_rmd()` for help creating this file. i Badge link will only be printed to screen. [ ] Copy and paste the following lines into 'README': @@ -51,7 +51,7 @@ use_r_universe_badge() Message ! Can't find a README for the current project. - i See `usethis::use_readme_rmd()` or `usethis::use_readme_rmd()` for help + i See `usethis::use_readme_qmd()` or `usethis::use_readme_rmd()` for help creating this file. i Badge link will only be printed to screen. [ ] Copy and paste the following lines into 'README': diff --git a/tests/testthat/_snaps/coverage.md b/tests/testthat/_snaps/coverage.md index 19ff973ab..11cd9f86b 100644 --- a/tests/testthat/_snaps/coverage.md +++ b/tests/testthat/_snaps/coverage.md @@ -4,7 +4,7 @@ use_codecov_badge("OWNER/REPO") Message ! Can't find a README for the current project. - i See `usethis::use_readme_rmd()` or `usethis::use_readme_rmd()` for help + i See `usethis::use_readme_qmd()` or `usethis::use_readme_rmd()` for help creating this file. i Badge link will only be printed to screen. [ ] Copy and paste the following lines into 'README': From ef02d485eb0b9e4395adc2bc0dcf63bf8849eab6 Mon Sep 17 00:00:00 2001 From: Jenny Bryan Date: Fri, 27 Feb 2026 15:23:56 -0800 Subject: [PATCH 3/3] Set this priority everywhere: qmd > Rmd > md --- R/badge.R | 6 +++--- R/readme.R | 20 ++++++++++---------- R/upkeep.R | 4 ++-- inst/templates/readme-rmd-pre-commit.sh | 6 +++--- man/badges.Rd | 4 ++-- man/use_readme_rmd.Rd | 20 ++++++++++---------- tests/testthat/_snaps/upkeep.md | 6 +++--- 7 files changed, 33 insertions(+), 33 deletions(-) diff --git a/R/badge.R b/R/badge.R index ec5f6cbe1..21834ba26 100644 --- a/R/badge.R +++ b/R/badge.R @@ -5,8 +5,8 @@ #' and link out to relevant external resources. To allow badges to be added #' automatically, ensure your badge block starts with a line containing only #' `` and ends with a line containing only -#' ``. The templates used by [use_readme_rmd()], -#' [use_readme_qmd()], and [use_readme_md()] and include this block. +#' ``. The templates used by [use_readme_qmd()], +#' [use_readme_rmd()], and [use_readme_md()] and include this block. #' #' @details #' @@ -224,5 +224,5 @@ badge_start <- "" badge_end <- "" find_readme <- function() { - path_first_existing(proj_path(c("README.Rmd", "README.qmd", "README.md"))) + path_first_existing(proj_path(c("README.qmd", "README.Rmd", "README.md"))) } diff --git a/R/readme.R b/R/readme.R index 7788c9c4a..e63ce2dca 100644 --- a/R/readme.R +++ b/R/readme.R @@ -6,23 +6,23 @@ #' * R code to install from GitHub, if GitHub usage detected #' * a basic example #' -#' Use `Rmd` or `qmd` if you want a rich intermingling of code and output. -#' Use `md` for a basic README. `README.Rmd` and `README.qmd` will be +#' Use `qmd` or `Rmd` if you want a rich intermingling of code and output. +#' Use `md` for a basic README. `README.qmd` and `README.Rmd` will be #' automatically added to `.Rbuildignore`. The resulting README is populated #' with default YAML frontmatter and R fenced code blocks (`md`) or -#' chunks (`Rmd`, `qmd`). +#' chunks (`qmd`, `Rmd`). #' -#' If you use `Rmd` or `qmd`, you'll still need to render it regularly, to +#' If you use `qmd` or `Rmd`, you'll still need to render it regularly, to #' keep `README.md` up-to-date. `devtools::build_readme()` is handy for -#' this. You could also use GitHub Actions to re-render `README.Rmd` or -#' `README.qmd` every time you push. An example workflow can be found in +#' this. You could also use GitHub Actions to re-render `README.qmd` or +#' `README.Rmd` every time you push. An example workflow can be found in #' the `examples/` directory here: #' . #' -#' If the current project is a Git repo, then `use_readme_rmd()` and -#' `use_readme_qmd()` automatically configure a pre-commit hook that helps +#' If the current project is a Git repo, then `use_readme_qmd()` and +#' `use_readme_rmd()` automatically configure a pre-commit hook that helps #' keep `README.md` synchronized with the source file. The hook creates -#' friction if you try to commit when `README.Rmd` or `README.qmd` has +#' friction if you try to commit when `README.qmd` or `README.Rmd` has #' been edited more recently than `README.md`. If this hook causes more #' problems than it solves for you, it is implemented in #' `.git/hooks/pre-commit`, which you can modify or even delete. @@ -34,8 +34,8 @@ #' @export #' @examples #' \dontrun{ -#' use_readme_rmd() #' use_readme_qmd() +#' use_readme_rmd() #' use_readme_md() #' } use_readme_rmd <- function(open = rlang::is_interactive()) { diff --git a/R/upkeep.R b/R/upkeep.R index 3d083dd42..a8dc1b169 100644 --- a/R/upkeep.R +++ b/R/upkeep.R @@ -63,7 +63,7 @@ upkeep_checklist <- function(target_repo = NULL) { bullets <- c( todo( - "`usethis::use_readme_rmd()` or `usethis::use_readme_qmd()`", + "`usethis::use_readme_qmd()` or `usethis::use_readme_rmd()`", !file_exists(proj_path("README.Rmd")) && !file_exists(proj_path("README.qmd")) ), @@ -165,7 +165,7 @@ tidy_upkeep_checklist <- function( bullets, "### Pre-history", "", - todo("`usethis::use_readme_rmd()` or `usethis::use_readme_qmd()`"), + todo("`usethis::use_readme_qmd()` or `usethis::use_readme_rmd()`"), todo("`usethis::use_roxygen_md()`"), todo("`usethis::use_github_links()`"), todo("`usethis::use_pkgdown_github_pages()`"), diff --git a/inst/templates/readme-rmd-pre-commit.sh b/inst/templates/readme-rmd-pre-commit.sh index f8126a51e..fce1e3845 100644 --- a/inst/templates/readme-rmd-pre-commit.sh +++ b/inst/templates/readme-rmd-pre-commit.sh @@ -6,10 +6,10 @@ if [[ ${#README[@]} == 0 ]]; then exit 0 fi -if [[ README.Rmd -nt README.md ]] || [[ README.qmd -nt README.md ]]; then - echo -e "README.md is out of date; please re-render README.Rmd/README.qmd\n$MSG" +if [[ README.qmd -nt README.md ]] || [[ README.Rmd -nt README.md ]]; then + echo -e "README.md is out of date; please re-render README.qmd/README.Rmd\n$MSG" exit 1 elif [[ ${#README[@]} -lt 2 ]]; then - echo -e "README.Rmd/README.qmd and README.md should be both staged\n$MSG" + echo -e "README.qmd/README.Rmd and README.md should be both staged\n$MSG" exit 1 fi diff --git a/man/badges.Rd b/man/badges.Rd index 49bc92634..962ede275 100644 --- a/man/badges.Rd +++ b/man/badges.Rd @@ -52,8 +52,8 @@ badges that report information, such as the CRAN version or test coverage, and link out to relevant external resources. To allow badges to be added automatically, ensure your badge block starts with a line containing only \verb{} and ends with a line containing only -\verb{}. The templates used by \code{\link[=use_readme_rmd]{use_readme_rmd()}}, -\code{\link[=use_readme_qmd]{use_readme_qmd()}}, and \code{\link[=use_readme_md]{use_readme_md()}} and include this block. +\verb{}. The templates used by \code{\link[=use_readme_qmd]{use_readme_qmd()}}, +\code{\link[=use_readme_rmd]{use_readme_rmd()}}, and \code{\link[=use_readme_md]{use_readme_md()}} and include this block. } \details{ \itemize{ diff --git a/man/use_readme_rmd.Rd b/man/use_readme_rmd.Rd index 6b43d8364..80123babc 100644 --- a/man/use_readme_rmd.Rd +++ b/man/use_readme_rmd.Rd @@ -24,31 +24,31 @@ Creates skeleton README files with possible stubs for \item a basic example } -Use \code{Rmd} or \code{qmd} if you want a rich intermingling of code and output. -Use \code{md} for a basic README. \code{README.Rmd} and \code{README.qmd} will be +Use \code{qmd} or \code{Rmd} if you want a rich intermingling of code and output. +Use \code{md} for a basic README. \code{README.qmd} and \code{README.Rmd} will be automatically added to \code{.Rbuildignore}. The resulting README is populated with default YAML frontmatter and R fenced code blocks (\code{md}) or -chunks (\code{Rmd}, \code{qmd}). +chunks (\code{qmd}, \code{Rmd}). -If you use \code{Rmd} or \code{qmd}, you'll still need to render it regularly, to +If you use \code{qmd} or \code{Rmd}, you'll still need to render it regularly, to keep \code{README.md} up-to-date. \code{devtools::build_readme()} is handy for -this. You could also use GitHub Actions to re-render \code{README.Rmd} or -\code{README.qmd} every time you push. An example workflow can be found in +this. You could also use GitHub Actions to re-render \code{README.qmd} or +\code{README.Rmd} every time you push. An example workflow can be found in the \verb{examples/} directory here: \url{https://github.com/r-lib/actions/}. -If the current project is a Git repo, then \code{use_readme_rmd()} and -\code{use_readme_qmd()} automatically configure a pre-commit hook that helps +If the current project is a Git repo, then \code{use_readme_qmd()} and +\code{use_readme_rmd()} automatically configure a pre-commit hook that helps keep \code{README.md} synchronized with the source file. The hook creates -friction if you try to commit when \code{README.Rmd} or \code{README.qmd} has +friction if you try to commit when \code{README.qmd} or \code{README.Rmd} has been edited more recently than \code{README.md}. If this hook causes more problems than it solves for you, it is implemented in \code{.git/hooks/pre-commit}, which you can modify or even delete. } \examples{ \dontrun{ -use_readme_rmd() use_readme_qmd() +use_readme_rmd() use_readme_md() } } diff --git a/tests/testthat/_snaps/upkeep.md b/tests/testthat/_snaps/upkeep.md index 791e25735..e21686061 100644 --- a/tests/testthat/_snaps/upkeep.md +++ b/tests/testthat/_snaps/upkeep.md @@ -9,7 +9,7 @@ ### Pre-history - * [ ] `usethis::use_readme_rmd()` or `usethis::use_readme_qmd()` + * [ ] `usethis::use_readme_qmd()` or `usethis::use_readme_rmd()` * [ ] `usethis::use_roxygen_md()` * [ ] `usethis::use_github_links()` * [ ] `usethis::use_pkgdown_github_pages()` @@ -122,7 +122,7 @@ Code writeLines(upkeep_checklist()) Output - * [ ] `usethis::use_readme_rmd()` or `usethis::use_readme_qmd()` + * [ ] `usethis::use_readme_qmd()` or `usethis::use_readme_rmd()` * [ ] `usethis::use_github_links()` * [ ] `usethis::use_pkgdown_github_pages()` * [ ] `usethis::use_tidy_description()` @@ -144,7 +144,7 @@ Code writeLines(checklist) Output - * [ ] `usethis::use_readme_rmd()` or `usethis::use_readme_qmd()` + * [ ] `usethis::use_readme_qmd()` or `usethis::use_readme_rmd()` * [ ] `usethis::use_github_links()` * [ ] `usethis::use_pkgdown_github_pages()` * [ ] `usethis::use_tidy_description()`