knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>",
  error = TRUE
)
library(googledrive)

Things I do in a hidden chunk here, to aid exposition about internal tooling:

drive_bullets <- googledrive:::drive_bullets
drive_abort <- googledrive:::drive_abort
bulletize <- gargle::bulletize
gargle_map_cli <- gargle::gargle_map_cli

auth_success <- tryCatch(
  googledrive:::drive_auth_docs(),
  googledrive_auth_internal_error = function(e) e
)

User-facing messages

Everything should be emitted by helpers in utils-ui.R: specifically, drive_bullets() (and, for errors, drive_abort()). These helpers are all wrappers around cli functions, such as cli::cli_bullets().

These may not demo well via pkgdown, but the interactive experience is nice.

drive_bullets(c(
        "noindent",
  " " = "indent",
  "*" = "bullet",
  ">" = "arrow",
  "v" = "success",
  "x" = "danger",
  "!" = "warning",
  "i" = "info"
))

The helpers encourage consistent styling and make it possible to selectively silence messages coming from googledrive. The googledrive message helpers:

Inline styling

How we use the inline classes:

drive_bullets(c(
  "We need to talk about the {.arg foofy} argument to {.fun blarg}",
  "You provided {.field a_very_weird_value} and I suspect you're confused \\
   about something"
))

Most relevant cli docs:

Bullets

I use the different bullet points in drive_bullets() to convey a mood.

Exclamation mark "!": I'm not throwing an error or warning, but I want to get the user's attention, because it seems likely (but not certain) that they misunderstand something about googledrive or Google Drive or their Drive files. Examples:

drive_bullets(c(
  "!" = "Ignoring {.arg type}. Only consulted for native Google file types.",
  " " = "MIME type of {.arg file}: {.field mime_type}."
))

drive_bullets(c(
  "!" = "Currently only fields for the {.field files} resource can be \\
         checked for validity.",
  " " = "Nothing done."
))

drive_bullets(c(
  "!" = "No updates specified."
))

drive_bullets(c(
  "!" = "No such file to delete."
))

Information "i": I'm just keeping you informed of how my work is going.

drive_bullets(c(
  "i" = "No pre-existing file at this filepath. Calling \\
         {.fun drive_upload}."
))

drive_bullets(c(
  "i" = "Pre-existing file at this filepath. Calling \\
         {.fun drive_update}."
))

drive_bullets(c(
  "i" = "Not logged in as any specific Google user."
))

In cases where we determine there is nothing we can or should do, sometimes I use "!" and sometimes I use "i". It depends on whether it feels like the user could or should have known that no work would be possible or needed.

Programmatic generation of bullets

Often we need to create bullets from an R object, such as a character vector or a dribble. What needs to happen:

gargle_map_cli() is a new generic in gargle that turns an object into a vector of strings with cli markup. Currently gargle exports methods for character (and NULL and a default) and googlesheets4 defines a method for dribble. This is likely to be replaced by something in cli itself in due course.

gargle_map_cli(letters[1:3])

By default gargle_map_cli.character() just applies the .field style, i.e. the template is "{.field <<x>>}". But the template can be customized, if you need something else. Note that we use non-standard glue delimiters (<< and >>, by default), because we are interpolating into a string with glue/cli markup, where {} has the usual meaning.

gargle_map_cli(letters[4:6], template = "how about a path {.path <<x>>}?")

The gargle_map_cli.dribble() method makes a cli-marked up string for each row of the dribble, i.e. for each Drive file.

dat <- drive_find(n_max = 5)
gargle_map_cli(dat)

gargle_map_cli.dribble() also allows a custom template, but it's a more complicated and less common situation than for character. We won't get into that here. (I don't consider the dribble styling to be finalized yet.)

The result of gargle_map_cli() then gets processed with gargle::bulletize(), which adds the bullet-specifying names and does aesthetically pleasing truncation.

bulletize(gargle_map_cli(letters))

bulletize(gargle_map_cli(letters), bullet = "x", n_show = 2)

drive_bullets(c(
  "These are surprising things:",
  bulletize(gargle_map_cli(letters), bullet = "!")
))

dat <- drive_find(n_max = 10)

drive_bullets(c(
  "Some Drive files:",
  bulletize(gargle_map_cli(dat))
))

It's conceivable that cli will gain a better way of vectorization, but this works for now.

Known dysfunction: it's inefficient to gargle_map_cli() over the whole object, then truncate with bulletize(). But it's easy. There are contexts, like tibble printing, where formatting stuff that will never see the light of day is really punishing. But I'm not sure I really have to worry about that.

Errors

I am currently using cli::cli_abort(), which is present in the dev version of cli (as of late May 2021, cli version 2.5.0.9000).

It's wrapped as drive_abort(), for the same reason as drive_bullets(), namely to apply some package-wide style tweaks.

The mechanics of drive_abort() usage are basically the same as drive_bullets().



tidyverse/googledrive documentation built on Jan. 14, 2024, 3:44 a.m.