无处不在的小插曲
在日常 R 用户眼中,关于小插曲需要记住的几件事......
- 可在 CRAN 包页面上找到(如果作者有的话,这是对包的一个很好的质量检查!)
- 添加到软件包二进制文件中并通过
browseVignettes(package = "pkgname")
[as you have pointed]显示在小插图帮助部分
- 嵌入在 R 包源中
- 可以在小插图中使用嵌入代码作为
/demos
via中的单独脚本演示demo()
- 最重要的部分:没有一个用户真正了解小插曲。
因此,如果您在软件包文档上花费了大量时间,您可能至少应该在启动时指出存在这样的功能。
为用户利益而开发packageStartupMessage()
内部。.onAttach()
在加载包时,控制台相对清晰,用户肯定会看到红色文本,因为普通蓝色 R 文本之间的对比度相对较高(假设没有蜡笔)。但是,在某些情况下,提醒用户注意小插曲的存在是没有意义的。
- 如果会话是非交互式的(例如 bash 脚本)。
- 如果用户是 R 'pro'
- 如果用户使用您的包很长时间,很长时间,导致用户无视消息。
因此,执行不力有负面影响packageStartupMessage()
。
因此,我建议在四种不同的条件下引入启动消息。
- (全部)通过查询来检查是否有人在场
interactive()
。如果是,则继续:
- (标准)拥有至少 3 条不同启动消息的列表,并在每次启动时随机选择一条进行显示;
- (正常)随机生成一个数字来判断是否应该显示启动信息;
- (专业版)计数包加载,
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"))
}
计算包裹负载
要使用计数器,我们利用保存到包的安装目录而不是“工作”目录/用户空间的能力。这有一些与之相关的问题,我将简要提及:
- 用户可能只有查看权限,但不能修改
system
库(用户库可以)。
- 因此,他们将始终在此方法下收到包提示,因为他们无法增加计数器。
- 如果包在
system
库中,则可能会共享计数器。
- 错误日志的大小可能会增加。
当然,您可以通过环境变量R_USER
或HOME
环境变量在用户空间内创建自己的文件夹来解决这些问题。(练习留给读者,提示:使用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
),它们可能有自己的一组启动消息,这些消息将在您的包中写入的消息之前显示。