8

我正在编写一个 R 包,并在文档小插曲上花费了大量时间。我想知道我是否应该添加类似的东西

.onAttach <- function( libname , pkgname ){
   packageStartupMessage("use `browseVignettes('packagename')` to see vignettes")
}

当用户调用时会立即显示

library(packagename)

告知用户有关包小插曲的最佳方式是什么?还是只是假设用户会在没有明确通知的情况下寻找它们?

4

2 回答 2

7

无处不在的小插曲

在日常 R 用户眼中,关于小插曲需要记住的几件事......

  1. 可在 CRAN 包页面上找到(如果作者有的话,这是对包的一个很好的质量检查!)
  2. 添加到软件包二进制文件中并通过browseVignettes(package = "pkgname")[as you have pointed]显示在小插图帮助部分
  3. 嵌入在 R 包源中
  4. 可以在小插图中使用嵌入代码作为/demosvia中的单独脚本演示demo()
  5. 最重要的部分:没有一个用户真正了解小插曲

因此,如果您在软件包文档上花费了大量时间,您可能至少应该在启动时指出存在这样的功能。

为用户利益而开发packageStartupMessage()内部。.onAttach()

在加载包时,控制台相对清晰,用户肯定会看到红色文本,因为普通蓝色 R 文本之间的对比度相对较高(假设没有蜡笔)。但是,在某些情况下,提醒用户注意小插曲的存在是没有意义的。

  1. 如果会话是非交互式的(例如 bash 脚本)。
  2. 如果用户是 R 'pro'
  3. 如果用户使用您的包很长时间,很长时间,导致用户无视消息。

因此,执行不力有负面影响packageStartupMessage()

因此,我建议在四种不同的条件下引入启动消息。

  1. (全部)通过查询来检查是否有人在场interactive()。如果是,则继续:
  2. (标准)拥有至少 3 条不同启动消息的列表,并在每次启动时随机选择一条进行显示;
  3. (正常)随机生成一个数字来判断是否应该显示启动信息;
  4. (专业版)计数包加载,x包加载后终止启动消息,直到用户重新安装包。

接下来我将介绍两种解决方案,它们遵循 (1) - (3) 的原则,然后为了简单起见仅介绍 (1) 和 (4)。

随机选择包提示

在这个版本中,我们试图简单地检查人类,提供一个中断添加包加载消息,并随机选择一个提示来显示。在 的范围之外只需要一个依赖项,即生成 [0,1] 之间概率base的命令。stats::runif

#' @importFrom stats runif
.onAttach <- function(...) {

  # If interactive, hide message
  # o.w. check against rng seed.
  if (!interactive() || stats::runif(1) > 0.5){
     return()
  }

  # Create a list of helpful tips
  pkg_hints = c(
    "Check for updates and report bugs at https://cran.r-project.org/web/packages/pkgname/.",
    "Use `suppressPackageStartupMessages()` to remove package startup messages.",
    "To see the user guides use `browseVignettes('pkgname')`"
  )

  # Randomly pick one hint
  startup_hint = sample(pkg_hints, 1)

  # Display hint
  packageStartupMessage(paste(strwrap(startup_hint), collapse = "\n"))
}

计算包裹负载

要使用计数器,我们利用保存到包的安装目录而不是“工作”目录/用户空间的能力。这有一些与之相关的问题,我将简要提及:

  1. 用户可能只有查看权限,但不能修改system库(用户库可以)。
    • 因此,他们将始终在此方法下收到包提示,因为他们无法增加计数器。
  2. 如果包在system库中,则可能会共享计数器。
    • 这将导致所有提示都被快速使用。
  3. 错误日志的大小可能会增加。

当然,您可以通过环境变量R_USERHOME环境变量在用户空间内创建自己的文件夹来解决这些问题。(练习留给读者,提示:使用Sys.getenv()dir.create()。)

无论如何,此功能的优点之一是稍后您可能会在包中包含“发送包使用统计信息”功能。这实际上会给出一个相当准确的 - 电话主页 - 统计数据与当前的 RStudio CRAN 镜像包下载信息。但是,我离题了。

为了使这种方法起作用,我们需要对提供给 CRAN 的初始包做更多的准备工作。具体来说,我们可能应该通过以下方式预先设置一个计数器:

# Set working directory to package
setwd("package_dir")

# Create the inst directory if it does not exist
if(!dir.exists("inst")){
  dir.create("inst")
}

# Create a counter variable
pkg_count = 0

# Save it into a .rda file
save(pkg_count, file="inst/counter.rda")

现在,进入.onAttach()柜台实施!

.onAttach <- function(...){
  if (!interactive()) return()

  # Get the install directory location of the counter
  path_count = system.file("counter.rda", package = "pkgname")

  # Suppress messages by default
  displayMsg = FALSE

  # Are we able to load the counter?
  a = tryCatch(load(path_count), error = function(e){"error"}, warning = function(e){"warning"})

  # Set error variable
  count_error = a %in% c("error","warning")

  # Check if the count is loaded
  if(!count_error){

    # Check if load count is low... 
    if(pkg_count < 10){
      pkg_count = pkg_count + 1

      # Try to save out
      try(save(pkg_count, file = path_count), silent=TRUE)
      displayMsg = T
    }
  }

  # Display message (can be suppressed with suppressPackageStartupMessages)
  if(displayMsg){
    packageStartupMessage("use `browseVignettes('packagename')` to see vignettes")
  }
}

最后的想法

请记住,如果您有任何包依赖项(例如Depend:in DESCRIPTION),它们可能有自己的一组启动消息,这些消息将在您的包中写入的消息之前显示。

于 2016-05-28T04:33:26.697 回答
6

我将提供相反的意见(StackOverflow 上是否允许意见?),即广告小插曲的启动消息没有帮助。包具有广泛依赖关系的情况越来越普遍,然后消息出现断章取义(为什么我在附加 Bar 时会得到包 Foo 的指导?),隐藏在其他包的启动消息中,与警告或错误,或压倒在过程的其他部分生成的潜在信息消息(例如,关于屏蔽符号)。此外,Bioconductor包小插曲非常常见,用户很快就会了解它们的价值(也是非Bioconductor包中可用的一些惊人小插曲的价值),因此用户可能不会像所描绘的那样不熟悉小插曲的存在和价值。

每一行代码都为错误提供了机会,因此编写复杂的代码来有条件地显示有关小插曲的信息并不是对程序员时间的宝贵利用,也不利于无缝的用户体验,尤其是当使用包需要成功执行代码时!在@Coatless 的解决方案中并且只是为了说明这一点,除了关注写入已安装的包位置之外,我还会对使用T而不是TRUEload()/save()而不是readRDS()/saveRDS()提出错误或警告的非特定方式被捕获但未传达给用户,引入额外的包依赖项(通过stats::runif()),并且可能在启动消息中使用降价符号。

相反,请在说明文件的说明:字段和各个帮助页面上引用小插图。

于 2016-05-28T21:19:20.757 回答