加载`library(packagename)`时提醒用户包装晕影的最佳做法?

时间:2016-05-28 04:04:39

标签: r r-package vignette

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

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

将在用户呼叫时立即显示

library(packagename)

告知用户有关包装晕影的最佳方法是什么?或者只是假设用户在没有明确通知的情况下会查找它们?

2 个答案:

答案 0 :(得分:7)

无处不在的小插曲

在日常R用户的眼中,很少有关于晕影的事情......

  1. 可在CRAN包装页面上找到(如果作者有一个,可以对包装进行质量检查!)
  2. 添加到包二进制文件中并通过browseVignettes(package = "pkgname") [正如您所指出的]显示在插图帮助部分
  3. 嵌入在R包源中
  4. 通过/demos
  5. demo() packageStartupMessage()中将插图代码中的嵌入代码用作单独的脚本演示的可能性
  6. 最重要的部分:根本没有用户真正了解插图
  7. 因此,如果您在软件包文档上花费了大量时间,那么至少应该在启动时指示存在这样的功能。

    .onAttach()内利用packageStartupMessage()为用户带来好处。

    在包加载时,控制台相对清晰,用户将肯定看到红色文本,因为正常蓝色R文本之间的对比度相对较高(假设没有crayon)。但是,在某些情况下,警告用户存在晕影是没有意义的。

    1. 如果会话是非交互式的(例如bash脚本)。
    2. 如果用户是R&#39;
    3. 如果用户长时间使用您的软件包,则会导致用户忽略消息。
    4. 因此,实施不当interactive()会产生负面影响。

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

      1. (全部)通过查询x来检查是否存在人。如果是,那么继续:
      2. (标准)列出至少3个不同的启动消息,并随机选择每个启动一个;
      3. (正常)随机生成一个数字以确定是否应显示启动消息;
      4. (Pro)在base包装加载后计算包装,在用户重新安装包装之前终止启动消息。
      5. 接下来,我将提出两个解决方案,其遵循(1) - (3)的原则,然后为了简单起见,仅提供(1)和(4)。

        随机选择包装提示

        在这个版本中,我们试图简单地检查人类,提供一个中断添加包加载消息,并随机选择一个提示显示。在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")) } 命令可以生成[0,1]之间的概率。

        system

        计算包装载

        要使用计数器,我们可以使用保存到软件包的安装目录中的功能,而不是&#34; working&#34;目录/用户空间。这有一些与之相关的问题,我将简要提及:

        1. 用户可能只有权查看但不能修改system库(用户库可以)。
          • 因此,他们将始终在此方法下接收包裹提示,因为他们无法递增计数器。
        2. 如果包位于Sys.getenv()库中,则可以共享计数器。
          • 这会导致所有提示快速使用。
        3. 错误日志的大小可能会增加。
        4. 当然,您可以通过R_USER or HOME environment variables在用户空间内创建自己的文件夹,以消除这些问题。 (练习留给读者,提示:使用dir.create()# 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") 。)

          无论如何,这个功能的一个优点是稍后您可能会包含一个&#34;发送包使用统计信息&#34;包内的功能。这实际上会提供一个相当准确的 - 电话主页 - 统计与当前的RStudio CRAN镜像包下载信息。但是,我离题了。

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

          .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:

          最后一个想法

          请记住,如果你有任何包依赖关系(例如DESCRIPTION中的include('somepath.php');),他们可能会有自己的一组启动消息显示< strong>之前在您的包中写的那些。

答案 1 :(得分:6)

我会提出相反的意见(StackOverflow上允许的观点吗?),宣传短片的启动消息没有帮助。对于包具有广泛的依赖性越来越常见,然后消息出现在上下文之外(为什么我在附加Bar时得到关于包Foo的指导?),被隐藏在其他包的启动消息中,与之混淆警告或错误,或压倒在该过程的其他部分中生成的潜在信息性消息(例如,关于屏蔽符号)。此外,Bioconductor包装短片很常见,用户很快就会了解它们的价值(也就是非 Bioconductor 包中可用的一些惊人的小插曲的价值),因此用户可能不会那么陌生与所描绘的小插曲的存在和价值有关。

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

相反,请在DESCRIPTION文件的Description:字段中以及各个帮助页面上引用晕影。