From 31294e2275709175f66f3a88a3724cc491e81720 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] 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..5f80a6e 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, .env$fuzzyhelp_url)) { + 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)) { + break + } else { + message("Waiting for fuzzyhelp UI to start") + Sys.sleep(0.5) + } + stop("Failed to open fuzzyhelp UI") + } + } else { + .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.