From 01f8d1afbb889ec87b5643db0edd15cea810b403 Mon Sep 17 00:00:00 2001 From: atusy <30277794+atusy@users.noreply.github.com> Date: Thu, 28 Mar 2024 09:37:49 +0900 Subject: [PATCH 1/7] fix(fuzzyhelp): broken addin --- R/fuzzyhelp.R | 52 ++++++++++++++++++++++++++++++++--------- inst/rstudio/addins.dcf | 2 +- man/fuzzyhelp.Rd | 7 +++++- 3 files changed, 48 insertions(+), 13 deletions(-) diff --git a/R/fuzzyhelp.R b/R/fuzzyhelp.R index d68fd58..409455a 100644 --- a/R/fuzzyhelp.R +++ b/R/fuzzyhelp.R @@ -379,6 +379,7 @@ create_server <- function(method = c("fzf", "lv")) { #' @param background Whether to run a shiny gadget in a background process. #' The default value is `TRUE` and can be changed by #' `option(fuzzyhelp.background = FALSE)`. +#' @inheritParams shiny::runGadget #' #' @note #' The default fuzzy match algorithm is a simplified version of @@ -397,13 +398,14 @@ create_server <- function(method = c("fzf", "lv")) { fuzzyhelp <- function( query = "", method = getOption("fuzzyhelp.method", "fzf"), - background = getOption("fuzzyhelp.background", TRUE)) { + background = getOption("fuzzyhelp.background", TRUE), + viewer = shiny::paneViewer()) { app <- create_ui(query) server <- create_server(method) # Create new gadget on foreground if (!background) { - shiny::runGadget(app, server) + shiny::runGadget(app, server, viewer = viewer) return(invisible(NULL)) } @@ -412,7 +414,30 @@ fuzzyhelp <- function( .env$fuzzyhelp_url <- tempfile() } - # Re-use existing gadget + # View existing gadget + if (fuzzyhelp_bg_view(viewer)) { + return(.env$fuzzyhelp) + } + + # Create new gadget on background + if (rstudioapi::isAvailable()) { + .env$fuzzyhelp <- fuzzyhelp_bg_start(app, server, identity) + for (i in 1:10) { # TODO: implement exponential backoff + if (fuzzyhelp_bg_view(viewer)) { + return(.env$fuzzyhelp) + } else { + message("Waiting for fuzzyhelp UI to start") + Sys.sleep(0.5) + } + } + stop("Failed to open fuzzyhelp UI") + } + + .env$fuzzyhelp <- fuzzyhelp_bg_start(app, server, viewer) + return(.env$fuzzyhelp) +} + +fuzzyhelp_bg_view <- function(viewer) { if ( !is.null(.env$fuzzyhelp) && is.null(.env$fuzzyhelp$get_exit_status()) && @@ -420,24 +445,29 @@ fuzzyhelp <- function( ) { url <- readLines(.env$fuzzyhelp_url)[1L] if (url != "") { - shiny::paneViewer()(url) - return(.env$fuzzyhelp) + viewer(url) + return(TRUE) } } + return(FALSE) +} - # Create new gadget on background - .env$fuzzyhelp <- callr::r_bg( - function(..., .env) { +fuzzyhelp_bg_start <- function(app, server, viewer) { + writeLines("", .env$fuzzyhelp_url) # Ensure content is empty + callr::r_bg( + function(..., .env, base_viewer) { viewer <- function(url) { writeLines(url, .env$fuzzyhelp_url) - shiny::paneViewer()(url) + base_viewer(url) } shiny::runGadget(..., viewer = viewer) }, - args = list(app = app, server = server, .env = .env), + args = list(app = app, server = server, .env = .env, base_viewer = viewer), env = Sys.getenv(), package = TRUE ) +} - return(.env$fuzzyhelp) +fuzzyhelp_addin <- function() { + fuzzyhelp(background = TRUE) } diff --git a/inst/rstudio/addins.dcf b/inst/rstudio/addins.dcf index 07e5654..010349f 100644 --- a/inst/rstudio/addins.dcf +++ b/inst/rstudio/addins.dcf @@ -1,4 +1,4 @@ Name: Fuzzy Search on R Help Description: Search and view help files with fuzzy queries. -Binding: fuzzyhelp +Binding: fuzzyhelp_addin Interactive: true diff --git a/man/fuzzyhelp.Rd b/man/fuzzyhelp.Rd index 37fcf87..74cc6ff 100644 --- a/man/fuzzyhelp.Rd +++ b/man/fuzzyhelp.Rd @@ -7,7 +7,8 @@ fuzzyhelp( query = "", method = getOption("fuzzyhelp.method", "fzf"), - background = getOption("fuzzyhelp.background", TRUE) + background = getOption("fuzzyhelp.background", TRUE), + viewer = shiny::paneViewer() ) } \arguments{ @@ -20,6 +21,10 @@ default value can be tweaked by \code{options(fuzzyhelp.method = "lv")}.} \item{background}{Whether to run a shiny gadget in a background process. The default value is \code{TRUE} and can be changed by \code{option(fuzzyhelp.background = FALSE)}.} + +\item{viewer}{Specify where the gadget should be displayed--viewer pane, +dialog window, or external browser--by passing in a call to one of the +\code{\link[shiny:viewer]{viewer()}} functions.} } \description{ Users no more have to afraid of exact name of the object they need help. From 891c8d112f7f2cfa82f993374c9888eeccc1a255 Mon Sep 17 00:00:00 2001 From: atusy <30277794+atusy@users.noreply.github.com> Date: Fri, 29 Mar 2024 07:21:35 +0900 Subject: [PATCH 2/7] feat(fuzzyhelp): on RStudio, retry view with exponential backoff --- R/fuzzyhelp.R | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/R/fuzzyhelp.R b/R/fuzzyhelp.R index 409455a..65713f3 100644 --- a/R/fuzzyhelp.R +++ b/R/fuzzyhelp.R @@ -421,16 +421,26 @@ fuzzyhelp <- function( # Create new gadget on background if (rstudioapi::isAvailable()) { + # Just start the UI without viewer because RStudio's viewer + # is not available fro the background process. .env$fuzzyhelp <- fuzzyhelp_bg_start(app, server, identity) - for (i in 1:10) { # TODO: implement exponential backoff + + # Wait and view UI in the main process. + min_seed <- 1L + for (i in c(rep(min_seed, 10L), seq(min_seed + 1, 10))) { if (fuzzyhelp_bg_view(viewer)) { return(.env$fuzzyhelp) } else { - message("Waiting for fuzzyhelp UI to start") - Sys.sleep(0.5) + # Wait with exponential backoff + t <- max((i**2) / 10, 0.5) + if (i > min_seed) { + # Don't be too noisy + message("Failed to open fuzzyhelp UI. Will retry in ", t, " seconds") + } + Sys.sleep(t) } } - stop("Failed to open fuzzyhelp UI") + stop("Failed to open fuzzyhelp UI. Try using fuzzyhelp(background = FALSE)") } .env$fuzzyhelp <- fuzzyhelp_bg_start(app, server, viewer) From 522140a1ac649e1cdecada4601986366dbf68a26 Mon Sep 17 00:00:00 2001 From: atusy <30277794+atusy@users.noreply.github.com> Date: Fri, 29 Mar 2024 07:22:31 +0900 Subject: [PATCH 3/7] feat(fuzzyhelp): improve browser opening behavior --- R/fuzzyhelp.R | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/R/fuzzyhelp.R b/R/fuzzyhelp.R index 65713f3..73e7e75 100644 --- a/R/fuzzyhelp.R +++ b/R/fuzzyhelp.R @@ -465,14 +465,21 @@ fuzzyhelp_bg_view <- function(viewer) { fuzzyhelp_bg_start <- function(app, server, viewer) { writeLines("", .env$fuzzyhelp_url) # Ensure content is empty callr::r_bg( - function(..., .env, base_viewer) { + function(..., .env, base_viewer, base_options) { + do.call(options, base_options) viewer <- function(url) { writeLines(url, .env$fuzzyhelp_url) base_viewer(url) } shiny::runGadget(..., viewer = viewer) }, - args = list(app = app, server = server, .env = .env, base_viewer = viewer), + args = list( + app = app, + server = server, + .env = .env, + base_viewer = viewer, + base_options = options() + ), env = Sys.getenv(), package = TRUE ) From 71200aafa1660a62524e996c74e075a050af98dc Mon Sep 17 00:00:00 2001 From: atusy <30277794+atusy@users.noreply.github.com> Date: Fri, 29 Mar 2024 08:56:41 +0900 Subject: [PATCH 4/7] docs(fuzzyhelp): update @return --- R/fuzzyhelp.R | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/R/fuzzyhelp.R b/R/fuzzyhelp.R index 73e7e75..6a4de2a 100644 --- a/R/fuzzyhelp.R +++ b/R/fuzzyhelp.R @@ -387,7 +387,9 @@ create_server <- function(method = c("fzf", "lv")) { #' excludes bonuses from relationship with matched characters and their #' previous characters. #' -#' @return NULL +#' @return +#' If the `background` argument is `TRUE`, then the return value inherits from +#' `callr::r_bg()`. Otherwise, `NULL` is returned. #' #' @examples #' if (FALSE) { From 410b2e13b1ab8cd2a4ad6a97350a3ad4fc6e5a10 Mon Sep 17 00:00:00 2001 From: atusy <30277794+atusy@users.noreply.github.com> Date: Fri, 29 Mar 2024 08:59:40 +0900 Subject: [PATCH 5/7] chore(docs): devtools::document() --- man/fuzzyhelp.Rd | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/man/fuzzyhelp.Rd b/man/fuzzyhelp.Rd index 74cc6ff..0f21c8d 100644 --- a/man/fuzzyhelp.Rd +++ b/man/fuzzyhelp.Rd @@ -26,6 +26,10 @@ The default value is \code{TRUE} and can be changed by dialog window, or external browser--by passing in a call to one of the \code{\link[shiny:viewer]{viewer()}} functions.} } +\value{ +If the \code{background} argument is \code{TRUE}, then the return value inherits from +\code{callr::r_bg()}. Otherwise, \code{NULL} is returned. +} \description{ Users no more have to afraid of exact name of the object they need help. A shiny gadget helps you to find a topic fuzzily. From 6e1d57a4ab31f737b45204e884cf943a56fa1444 Mon Sep 17 00:00:00 2001 From: atusy <30277794+atusy@users.noreply.github.com> Date: Fri, 29 Mar 2024 09:01:18 +0900 Subject: [PATCH 6/7] docs(NEWS): mention PR numbers --- NEWS.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NEWS.md b/NEWS.md index fdde48e..e80ef21 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,10 +1,10 @@ # felp 0.3.0.9999 - Support `fuzzyhelp` to run Shiny App in background without blocking user terminal. - The new behavior is enabled by default and can be disabled by passing `FALSE` to the `background` argument or to the `fuzzyhelp.background` option. + The new behavior is enabled by default and can be disabled by passing `FALSE` to the `background` argument or to the `fuzzyhelp.background` option (#18, #20). - Fixed wrong behaviors of anchors in the HTML help in the UI of the `fuzzyhelp` function. A click on a anchor should not cause nesting of the UI when href of the anchor is an ID. - Instead, the click should scroll the window to show the element with the corresponding ID. + Instead, the click should scroll the window to show the element with the corresponding ID (#17). # felp 0.3.0 From c3fd3585507f11ebc8ee07216195813cbfcf16e0 Mon Sep 17 00:00:00 2001 From: atusy <30277794+atusy@users.noreply.github.com> Date: Fri, 29 Mar 2024 09:03:13 +0900 Subject: [PATCH 7/7] chore(docs): pkgdown::build_site() --- docs/articles/felp.html | 2 +- docs/news/index.html | 4 ++-- docs/pkgdown.yml | 2 +- docs/reference/fuzzyhelp.html | 16 +++++++++++++++- 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/docs/articles/felp.html b/docs/articles/felp.html index 6062172..456f5ba 100644 --- a/docs/articles/felp.html +++ b/docs/articles/felp.html @@ -323,7 +323,7 @@
fuzzyhelp
to run Shiny App in background without blocking user terminal. The new behavior is enabled by default and can be disabled by passing FALSE
to the background
argument or to the fuzzyhelp.background
option.fuzzyhelp
function. A click on a anchor should not cause nesting of the UI when href of the anchor is an ID. Instead, the click should scroll the window to show the element with the corresponding ID.fuzzyhelp
to run Shiny App in background without blocking user terminal. The new behavior is enabled by default and can be disabled by passing FALSE
to the background
argument or to the fuzzyhelp.background
option (#18, #20).fuzzyhelp
function. A click on a anchor should not cause nesting of the UI when href of the anchor is an ID. Instead, the click should scroll the window to show the element with the corresponding ID (#17).fuzzyhelp(
query = "",
method = getOption("fuzzyhelp.method", "fzf"),
- background = getOption("fuzzyhelp.background", TRUE)
+ background = getOption("fuzzyhelp.background", TRUE),
+ viewer = shiny::paneViewer()
)
TRUE
and can be changed by
option(fuzzyhelp.background = FALSE)
.
+
+Specify where the gadget should be displayed--viewer pane,
+dialog window, or external browser--by passing in a call to one of the
+viewer()
functions.
If the background
argument is TRUE
, then the return value inherits from
+callr::r_bg()
. Otherwise, NULL
is returned.
The default fuzzy match algorithm is a simplified version of