Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use cli #1956

Merged
merged 111 commits into from Mar 4, 2024
Merged

Use cli #1956

Show file tree
Hide file tree
Changes from 101 commits
Commits
Show all changes
111 commits
Select commit Hold shift + click to select a range
1dc845c
Init article on the conversion task
jennybc Feb 12, 2024
f7b906a
Build up the cli-based UI in one place
jennybc Feb 13, 2024
2194623
Introduce ui_cli_bullets()
jennybc Feb 13, 2024
26f1d31
author.R
jennybc Feb 13, 2024
7c96412
Factor out the path-processing logic into ui_path_impl()
jennybc Feb 15, 2024
1a63223
addin.R
jennybc Feb 13, 2024
de288ca
ui_bullets() is better because shorter
jennybc Feb 13, 2024
1db32b4
badge.R
jennybc Feb 15, 2024
4ab8df7
ui_abort() feels more consistent with everything else
jennybc Feb 13, 2024
5827019
Introduce ui_code_snippet()
jennybc Feb 15, 2024
fa943c2
block.R
jennybc Feb 15, 2024
d4b4009
Some testing improvements
jennybc Feb 16, 2024
c8b7c62
Test ui_code_snippet()
jennybc Feb 16, 2024
2fb1a4c
Replace all calls to ui_code_block()
jennybc Feb 16, 2024
5377788
Typo
jennybc Feb 16, 2024
4251e5c
Update conversion article
jennybc Feb 16, 2024
8a7a250
browse.R
jennybc Feb 16, 2024
46a9f22
Eliminate usage of ui_warn()
jennybc Feb 16, 2024
87783e8
ci.R
jennybc Feb 16, 2024
d500a8f
code_of_conduct.R
jennybc Feb 16, 2024
da160a9
course.R
jennybc Feb 16, 2024
cd7e298
coverage.R
jennybc Feb 16, 2024
fb2e179
cpp11.R
jennybc Feb 16, 2024
c9ef28c
Single quote inline .field if no color
jennybc Feb 17, 2024
681ad46
create.R
jennybc Feb 17, 2024
582d271
data.R
jennybc Feb 26, 2024
8186323
description.R
jennybc Feb 17, 2024
bf88fde
directory.R
jennybc Feb 17, 2024
a468a4a
edit.R
jennybc Feb 18, 2024
2530f03
git-default-branch.R
jennybc Feb 21, 2024
73b986c
git.R
jennybc Feb 21, 2024
a64ecf4
Test bulletize() and usethis_map_cli()
jennybc Feb 21, 2024
bcb5f6b
github-actions.R
jennybc Feb 22, 2024
8de285e
.val seems like a better default for usethis
jennybc Feb 22, 2024
7e9aeb9
github-labels.R
jennybc Feb 22, 2024
776b4a0
github-pages.R
jennybc Feb 22, 2024
bd730c1
github.R + check_current_branch()
jennybc Feb 22, 2024
2e97e4f
github_token.R
jennybc Feb 22, 2024
ab2120d
Remove hd_line() which is not used anywhere at this point
jennybc Feb 22, 2024
0ece8f4
Notes
jennybc Feb 23, 2024
e6d365c
Modernize kv_line() + other changes to improve git_sitrep()
jennybc Feb 23, 2024
e1b2d97
github_token.R
jennybc Feb 23, 2024
5e44d17
helpers.R
jennybc Feb 23, 2024
bfd87d7
issue.R
jennybc Feb 23, 2024
142c1fa
license.R
jennybc Feb 23, 2024
48346b0
lifecycle.R
jennybc Feb 23, 2024
c85f779
logo.R
jennybc Feb 23, 2024
0e8252c
news.R
jennybc Feb 23, 2024
55f0819
package.R
jennybc Feb 23, 2024
1e3f5c8
pkgdown.R
jennybc Feb 23, 2024
bba1926
Provide default bullets in ui_abort()
jennybc Feb 24, 2024
89b8a1b
pr.R
jennybc Feb 24, 2024
6467992
proj-desc.R
jennybc Feb 24, 2024
cb51d5f
proj.R
jennybc Feb 24, 2024
dd3d14f
rcpp.R
jennybc Feb 24, 2024
b0fe620
readme.R
jennybc Feb 24, 2024
8c89ffe
release.R
jennybc Feb 24, 2024
42bfc88
rename-files.R
jennybc Feb 24, 2024
9f5d79b
revdep.R
jennybc Feb 24, 2024
ae18ced
roxygen.R
jennybc Feb 24, 2024
5075412
rprofile.R
jennybc Feb 24, 2024
83161d7
rstudio.R
jennybc Feb 24, 2024
4eab6d4
sitrep.R
jennybc Feb 24, 2024
747629c
spelling.R
jennybc Feb 24, 2024
4b40d27
template.R
jennybc Feb 24, 2024
1b5a8d0
test.R
jennybc Feb 24, 2024
d7c2a89
tibble.R
jennybc Feb 24, 2024
a1f1d0e
tidyverse.R
jennybc Feb 24, 2024
4bd21a1
upkeep.R
jennybc Feb 24, 2024
b9311c1
use_github_file.R
jennybc Feb 24, 2024
a6d8e97
use_import_fun.R
jennybc Feb 24, 2024
8b0ccad
usethis-defunct.R
jennybc Feb 24, 2024
fd254f8
Rename to ui_legacy_bullet(); catch up on note-taking
jennybc Feb 25, 2024
c1f5d48
utils-git.R
jennybc Feb 26, 2024
7cb0602
utils.R
jennybc Feb 25, 2024
5f80d3a
version.R
jennybc Feb 25, 2024
a9ae363
vignette.R
jennybc Feb 25, 2024
42b7c28
write.R
jennybc Feb 25, 2024
8e390e7
utils-github.R
jennybc Feb 26, 2024
043e8cf
Add snapshot tests for remote GitHub configurations
jennybc Feb 27, 2024
667c148
Finish converting UI around GitHub remote configurations
jennybc Feb 27, 2024
f7f5ee0
Refactor flaky test
jennybc Feb 27, 2024
25dcfdc
Better organization
jennybc Feb 27, 2024
f5b380d
Catch up on note-taking
jennybc Feb 27, 2024
de7e066
Work on making the article actually render the way I want
jennybc Feb 27, 2024
86b3278
Mark ui_*() functions as superseded
jennybc Feb 28, 2024
6333976
Mark ui_yeah() and ui_no() as superseded
jennybc Feb 29, 2024
e0df61c
Work on kv_line()
jennybc Feb 29, 2024
397e0ac
Use ui_yep() and ui_nah() everywhere
jennybc Feb 29, 2024
c71ed6b
Re-align filenames re: legacy ui
jennybc Feb 29, 2024
4653e81
OMG I don't want people to depend on usethis for ui functions
jennybc Feb 29, 2024
7f99c38
Switch to ui_nah() , for real
jennybc Feb 29, 2024
cb91031
Make sure I don't call into the legacy file
jennybc Feb 29, 2024
2aaa255
Deal with stragglers that are not TODOs
jennybc Feb 29, 2024
b25065c
Update principles.md
jennybc Feb 29, 2024
d0cc81e
NEWS bullet
jennybc Feb 29, 2024
a3ab22b
Yet another straggler
jennybc Feb 29, 2024
b2805d2
Deal with utils::menu() prep and other unusual stuff
jennybc Feb 29, 2024
c462abf
Make test less sensitive to local conditions
jennybc Mar 1, 2024
12ee388
Article needs asciicast
jennybc Mar 1, 2024
c1c9297
Increase width to forcibly prevent snapshot diff due to linebreaks
jennybc Mar 1, 2024
db3c536
Organize the articles
jennybc Mar 1, 2024
9143717
Update README
jennybc Mar 1, 2024
d7b30f7
Make the width even larger???
jennybc Mar 1, 2024
226c4a0
Apply suggestions from code review
jennybc Mar 1, 2024
4cea077
Update snapshot
jennybc Mar 1, 2024
0baf2b5
How about cli.width?????
jennybc Mar 1, 2024
3e343a3
YOLO
jennybc Mar 1, 2024
210905f
`.run` fixups
jennybc Mar 1, 2024
56c130c
These run afoul of the `.run` rules, so why bother
jennybc Mar 1, 2024
d6a3552
Better captures the intent
jennybc Mar 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion DESCRIPTION
Expand Up @@ -53,7 +53,7 @@ Suggests:
spelling (>= 1.2),
styler (>= 1.2.0),
testthat (>= 3.1.8)
Config/Needs/website: tidyverse/tidytemplate, xml2
Config/Needs/website: r-lib/asciicast, tidyverse/tidytemplate, xml2
Config/testthat/edition: 3
Config/testthat/parallel: TRUE
Config/testthat/start-first: github-actions, release
Expand Down
3 changes: 3 additions & 0 deletions NAMESPACE
Expand Up @@ -3,6 +3,9 @@
S3method(format,github_remote_config)
S3method(print,github_remote_config)
S3method(print,sitrep)
S3method(usethis_map_cli,"NULL")
S3method(usethis_map_cli,character)
S3method(usethis_map_cli,default)
export(browse_circleci)
export(browse_cran)
export(browse_github)
Expand Down
13 changes: 13 additions & 0 deletions NEWS.md
@@ -1,5 +1,18 @@
# usethis (development version)

* The `ui_*()` functions have been marked as
[superseded](https://lifecycle.r-lib.org/articles/stages.html#superseded).
External users of these functions are encouraged to use the
[cli package](https://cli.r-lib.org/) instead.
The cli package did not have the required functionality when the
`usethis::ui_*()` functions were first created, but it does now and it's the
superior option.
There is a cli vignette about how to make this transition:
`vignette("usethis-ui", package = "cli")`.

usethis no longer uses the `ui_*()` functions internally, in favor of new
cli-based helpers that are not exported.

# usethis 2.2.3

* Patch release with changes to `.Rd` files requested by CRAN.
Expand Down
6 changes: 4 additions & 2 deletions R/addin.R
Expand Up @@ -15,13 +15,15 @@ use_addin <- function(addin = "new_addin", open = rlang::is_interactive()) {
if (!file_exists(addin_dcf_path)) {
create_directory(proj_path("inst", "rstudio"))
file_create(addin_dcf_path)
ui_done("Creating {ui_path(addin_dcf_path)}")
ui_bullets(c("v" = "Creating {.path {pth(addin_dcf_path)}}"))
Copy link
Member Author

@jennybc jennybc Feb 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ui_bullets() is a new unexported wrapper around cli::cli_bullets() that applies a custom usethis style and honors the usethis.quiet option. All of the old "block styles" get replaced by ui_bullets().

{.path {pth(addin_dcf_path)}} is a clunky but effective pattern you will see a lot of. This is explained more fully in the article.

pth() is an internal helper that forms paths relative to a base and it's super important in usethis. But I also really, really want cli's file hyperlinks. I don't see a way to create a custom inline span that allows me to combine my pre-processsing with cli's file hyperlink support. But I'd love to learn that I'm wrong.

}

addin_info <- render_template("addins.dcf", data = list(addin = addin))
addin_info[length(addin_info) + 1] <- ""
write_utf8(addin_dcf_path, addin_info, append = TRUE)
ui_done("Adding binding to {ui_code(addin)} to addins.dcf.")
ui_bullets(c(
"v" = "Adding binding to {.fun {addin}} to {.path addins.dcf}"
))

if (open) {
edit_file(addin_dcf_path)
Expand Down
53 changes: 28 additions & 25 deletions R/author.R
Expand Up @@ -60,13 +60,15 @@ use_author <- function(given = NULL, family = NULL, ..., role = "ctb") {
author <- utils::person(given = given, family = family, role = role, ...)
aut_fmt <- format(author, style = 'text')
if (authors_at_r_already) {
ui_done("
Adding to {ui_field('Authors@R')} in DESCRIPTION:
{aut_fmt}")
ui_bullets(c(
"v" = "Adding to {.field Authors@R} in DESCRIPTION:",
" " = "{aut_fmt}"
))
} else {
ui_done("
Creating {ui_field('Authors@R')} field in DESCRIPTION and adding:
{aut_fmt}")
ui_bullets(c(
"v" = "Creating {.field Authors@R} field in DESCRIPTION and adding:",
" " = "{aut_fmt}"
))
}
d$add_author(given = given, family = family, role = role, ...)

Expand All @@ -84,17 +86,17 @@ challenge_legacy_author_fields <- function(d = proj_desc()) {
return(invisible())
}

ui_oops("
Found legacy {ui_field('Author')} and/or {ui_field('Maintainer')} field \\
in DESCRIPTION.
usethis only supports modification of the {ui_field('Authors@R')} field.")
ui_info("
We recommend one of these paths forward:
* Delete these fields and rebuild with {ui_code('use_author()')}.
* Convert to {ui_field('Authors@R')} with {ui_code('desc::desc_coerce_authors_at_r()')},
then delete the legacy fields.")
if (ui_yeah("Do you want to cancel this operation and sort that out first?")) {
ui_stop("Cancelling.")
ui_bullets(c(
"x" = "Found legacy {.field Author} and/or {.field Maintainer} field in
DESCRIPTION.",
" " = "usethis only supports modification of the {.field Authors@R} field.",
"i" = "We recommend one of these paths forward:",
"_" = "Delete the legacy fields and rebuild with {.fun use_author}; or",
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I introduce a new bullet type with shortcode "_". This is for TODOs and is meant to evoke a place where you could check something off.

"_" = "Convert to {.field Authors@R} with
{.fun desc::desc_coerce_authors_at_r}, then delete the legacy fields."
))
if (ui_yep("Do you want to cancel this operation and sort that out first?")) {
ui_abort("Cancelling.")
}
invisible()
}
Expand All @@ -108,10 +110,10 @@ check_author_is_novel <- function(given = NULL, family = NULL, d = proj_desc())
})
if (any(m)) {
aut_name <- glue("{given %||% ''} {family %||% ''}")
usethis_abort(c(
"{.val {aut_name}} already appears in {.val Authors@R}.",
"Please make the desired change directly in DESCRIPTION or call the \\
desc package directly."
ui_abort(c(
"x" = "{.val {aut_name}} already appears in {.field Authors@R}.",
" " = "Please make the desired change directly in DESCRIPTION or call the
{.pkg desc} package directly."
))
}
invisible()
Expand All @@ -129,10 +131,11 @@ challenge_default_author <- function(d = proj_desc()) {
)

if (any(m)) {
ui_info("
{ui_field('Authors@R')} appears to include a placeholder author:
{format(default_author, style = 'text')}")
if(is_interactive() && ui_yeah("Would you like to remove it?")) {
ui_bullets(c(
"i" = "{.field Authors@R} appears to include a placeholder author:",
" " = "{format(default_author, style = 'text')}"
))
if(is_interactive() && ui_yep("Would you like to remove it?")) {
# TODO: Do I want to suppress this output?
# Authors removed: First Last, NULL NULL.
do.call(d$del_author, unclass(default_author)[[1]])
Expand Down
24 changes: 13 additions & 11 deletions R/badge.R
Expand Up @@ -43,23 +43,25 @@ NULL
use_badge <- function(badge_name, href, src) {
path <- find_readme()
if (is.null(path)) {
ui_oops("
Can't find a README for the current project.
See {ui_code('usethis::use_readme_rmd()')} for help creating this file.
Badge link can only be printed to screen.
")
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" = "Badge link will only be printed to screen."
))
path <- "README"
}
changed <- block_append(
glue("{ui_field(badge_name)} badge"),
glue("{badge_name} badge"),
glue("[![{badge_name}]({src})]({href})"),
path = path,
block_start = badge_start,
block_end = badge_end
)

if (changed && path_ext(path) == "Rmd") {
ui_todo("Re-knit {ui_path(path)} with {ui_code('devtools::build_readme()')}")
ui_bullets(c(
"_" = "Re-knit {.path {pth(path)}} with {.fun devtools::build_readme}."
jennybc marked this conversation as resolved.
Show resolved Hide resolved
))
}
invisible(changed)
}
Expand Down Expand Up @@ -153,10 +155,10 @@ use_posit_cloud_badge <- function(url) {
img <- "https://img.shields.io/badge/launch-posit%20cloud-447099?style=flat"
use_badge("Launch Posit Cloud", url, img)
} else {
usethis_abort("
{.fun usethis::use_posit_cloud_badge} requires a link to an \\
existing Posit Cloud project of the form \\
{.val https://posit.cloud/content/<project-id>} or \\
ui_abort("
{.fun usethis::use_posit_cloud_badge} requires a link to an
existing Posit Cloud project of the form
{.val https://posit.cloud/content/<project-id>} or
{.val https://posit.cloud/spaces/<space-id>/content/<project-id>}.")
}

Expand Down
26 changes: 15 additions & 11 deletions R/block.R
Expand Up @@ -16,13 +16,14 @@ block_append <- function(desc, value, path,
}

if (is.null(block_lines)) {
ui_todo("
Copy and paste the following lines into {ui_path(path)}:")
ui_code_block(c(block_prefix, block_start, value, block_end, block_suffix))
ui_bullets(c(
"_" = "Copy and paste the following lines into {.path {pth(path)}}:"
))
ui_code_snippet(c(block_prefix, block_start, value, block_end, block_suffix))
return(FALSE)
}

ui_done("Adding {desc} to {ui_path(path)}")
ui_bullets(c("v" = "Adding {.val {desc}} to {.path {pth(path)}}."))

start <- block_lines[[1]]
end <- block_lines[[2]]
Expand Down Expand Up @@ -54,8 +55,10 @@ block_replace <- function(desc, value, path,
}

if (is.null(block_lines)) {
ui_todo("Copy and paste the following lines into {ui_value(path)}:")
ui_code_block(c(block_start, value, block_end))
ui_bullets(c(
"_" = "Copy and paste the following lines into {.path {pth(path)}}:"
))
ui_code_snippet(c(block_start, value, block_end))
return(invisible(FALSE))
}

Expand All @@ -67,7 +70,7 @@ block_replace <- function(desc, value, path,
return(invisible(FALSE))
}

ui_done("Replacing {desc} in {ui_path(path)}")
ui_bullets(c("v" = "Replacing {desc} in {.path {pth(path)}}."))

lines <- c(
lines[seq2(1, start - 1L)],
Expand Down Expand Up @@ -99,10 +102,11 @@ block_find <- function(lines, block_start = "# <<<", block_end = "# >>>") {
}

if (!(length(start) == 1 && length(end) == 1 && start < end)) {
ui_stop(
"Invalid block specification.
Must start with {ui_code(block_start)} and end with {ui_code(block_end)}"
)
ui_abort(c(
"Invalid block specification.",
"Must start with {.code {block_start}} and end with
{.code {block_end}}."
))
}

c(start + 1L, end - 1L)
Expand Down
39 changes: 22 additions & 17 deletions R/browse.R
Expand Up @@ -77,7 +77,10 @@ browse_package <- function(package = NULL) {
grl <- set_names(grl$url, nm = grl$remote)
parsed <- parse_github_remotes(grl)
urls <- c(urls, glue_data(parsed, "https://{host}/{repo_owner}/{repo_name}"))
details <- c(details, map(parsed$name, ~ glue("{ui_value(.x)} remote")))
details <- c(
details,
map(parsed$name, ~ cli::cli_fmt(cli::cli_text("{.val {.x}} remote")))
)
}

desc_urls_dat <- desc_urls(package, include_cran = TRUE)
Expand All @@ -86,11 +89,11 @@ browse_package <- function(package = NULL) {
details,
map(
desc_urls_dat$desc_field,
~ if (is.na(.x)) "CRAN" else glue("{ui_field(.x)} field in DESCRIPTION")
~ if (is.na(.x)) "CRAN" else cli::cli_fmt(cli::cli_text("{.field {.x}} field in DESCRIPTION"))
)
)
if (length(urls) == 0) {
ui_oops("Can't find any URLs")
ui_bullets(c(x = "Can't find any URLs."))
return(invisible(character()))
}

Expand Down Expand Up @@ -171,15 +174,17 @@ github_url <- function(package = NULL) {

if (is.null(desc_urls_dat)) {
if (is.null(package)) {
ui_stop("
Project {ui_value(project_name())} has no DESCRIPTION file and \\
has no GitHub remotes configured
No way to discover URLs")
ui_abort(c(
"Project {.val {project_name()}} has no DESCRIPTION file and
has no GitHub remotes configured.",
"No way to discover URLs."
))
} else {
ui_stop("
Can't find DESCRIPTION for package {ui_value(package)} locally \\
or on CRAN
No way to discover URLs")
ui_abort(c(
"Can't find DESCRIPTION for package {.pkg {package}} locally
or on CRAN.",
"No way to discover URLs."
))
}
}

Expand All @@ -191,13 +196,13 @@ github_url <- function(package = NULL) {
}

if (is.null(package)) {
ui_stop("
Project {ui_value(project_name())} has no GitHub remotes configured \\
and has no GitHub URLs in DESCRIPTION")
ui_abort("
Project {.val {project_name()}} has no GitHub remotes configured
and has no GitHub URLs in DESCRIPTION.")
}
ui_warn("
Package {ui_value(package)} has no GitHub URLs in DESCRIPTION
Trying the GitHub CRAN mirror")
cli::cli_warn(c(
"!" = "Package {.val {package}} has no GitHub URLs in DESCRIPTION.",
" " = "Trying the GitHub CRAN mirror."))
glue_chr("https://github.com/cran/{package}")
}

Expand Down
4 changes: 3 additions & 1 deletion R/ci.R
Expand Up @@ -82,7 +82,9 @@ use_circleci_badge <- function(repo_spec = NULL) {

circleci_activate <- function(owner, browse = is_interactive()) {
url <- glue("https://circleci.com/add-projects/gh/{owner}")
ui_todo("Turn on CircleCI for your repo at {url}")
ui_bullets(c(
"_" = "Turn on CircleCI for your repo at {.url {url}}."
))
if (browse) {
utils::browseURL(url)
}
Expand Down
14 changes: 8 additions & 6 deletions R/code-of-conduct.R
Expand Up @@ -23,9 +23,8 @@
#' @export
use_code_of_conduct <- function(contact, path = NULL) {
if (missing(contact)) {
ui_stop("
{ui_code('use_code_of_conduct()')} requires contact details in \\
first argument")
ui_abort("
{.fun use_code_of_conduct} requires contact details in first argument.")
}

new <- use_coc(contact = contact, path = path)
Expand All @@ -35,13 +34,16 @@ use_code_of_conduct <- function(contact, path = NULL) {
href <- sub("/$", "", href)
href <- paste0(href, "/CODE_OF_CONDUCT.html")

ui_todo("You may also want to describe the code of conduct in your README:")
ui_code_block("
ui_bullets(c(
"_" = "You may also want to describe the code of conduct in your README:"
))
ui_code_snippet("
## Code of Conduct

Please note that the {project_name()} project is released with a \\
[Contributor Code of Conduct]({href}). By contributing to this project, \\
you agree to abide by its terms."
you agree to abide by its terms.",
language = ""
)

invisible(new)
Expand Down