🔍 An RStudio addin slash regex utility belt
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

178 rindas
5.4KB

  1. #' RegExplain gadget
  2. #'
  3. #' The function behind the RegExplain Selection and RegExplain File
  4. #' addins. Opens the RegExplain gadget interface in an RStudio viewer
  5. #' pane.
  6. #'
  7. #' @import miniUI
  8. #' @import shiny
  9. #' @param text Text to explore in gadget (editable using interface)
  10. #' @param pattern Regular Expression to edit or visualize using RegExplain
  11. #' @param start_page Open gadget to this tab, one of `"Text"`, `"RegEx"`,
  12. #' `"Output"`, or `"Help"`
  13. #' @export
  14. regexplain_gadget <- function(
  15. text = NULL,
  16. pattern = NULL,
  17. start_page = if (is.null(text)) "Text" else "RegEx"
  18. ) {
  19. stopifnot(requireNamespace("miniUI"), requireNamespace("shiny"))
  20. viewer <- shiny::paneViewer(minHeight = 800)
  21. runGadget(
  22. regexplain_gadget_ui(text, pattern, start_page),
  23. regexplain_gadget_server(check_version()),
  24. viewer = viewer)
  25. }
  26. #' @describeIn regexplain_gadget Launches the RegExplain gadget in a browser or an
  27. #' RStduio viewer pane.
  28. #' @inheritDotParams shiny::shinyApp
  29. #' @export
  30. regexplain_web <- function(text = NULL, pattern = NULL, start_page = "Text", ...) {
  31. stopifnot(requireNamespace("miniUI"), requireNamespace("shiny"))
  32. shinyApp(
  33. regexplain_gadget_ui(text, pattern, start_page),
  34. regexplain_gadget_server(check_version()), ...)
  35. }
  36. # ---- Gadget Helper Functions and Variables ----
  37. sanitize_text_input <- function(x) {
  38. if (is.null(x) || !nchar(x)) return(x)
  39. rx_unicode <- "\\\\u[0-9a-f]{4,8}"
  40. rx_hex <- "\\\\x[0-9a-f]{2}|\\\\x\\{[0-9a-f]{1,6}\\}"
  41. rx_octal <- "\\\\[0][0-7]{1,3}"
  42. rx_escape <- paste(rx_unicode, rx_hex, rx_octal, sep = "|")
  43. if (grepl(rx_escape, x, ignore.case = TRUE)) {
  44. try({
  45. y <- stringi::stri_unescape_unicode(x)
  46. }, silent = TRUE)
  47. if (!is.na(y)) x <- y
  48. }
  49. # x <- gsub("\u201C|\u201D", '"', x)
  50. # x <- gsub("\u2018|\u2019", "'", x)
  51. x
  52. }
  53. toHTML <- function(...) {
  54. x <- paste(..., collapse = "")
  55. x <- gsub("\n", "\\\\n", x)
  56. x <- gsub("\t", "\\\\t", x)
  57. x <- gsub("\r", "\\\\r", x)
  58. HTML(x)
  59. }
  60. regexFn_choices <- list(
  61. "Choose a function" = "",
  62. base = c(
  63. "grep",
  64. "grepl",
  65. "sub", #<<
  66. "gsub", #<<
  67. "regexpr",
  68. "gregexpr",
  69. "regexec"
  70. ),
  71. stringr = c(
  72. "str_detect",
  73. "str_locate",
  74. "str_locate_all",
  75. "str_extract",
  76. "str_extract_all",
  77. "str_match",
  78. "str_match_all",
  79. "str_replace", #<<
  80. "str_replace_all", #<<
  81. "str_split"
  82. ),
  83. "rematch2" = c(
  84. "re_match",
  85. "re_match_all",
  86. "re_exec",
  87. "re_exec_all"
  88. )
  89. )
  90. regexFn_substitute <- c(
  91. paste0(c("", "g"), "sub"),
  92. paste0("str_replace", c("", "_all"))
  93. )
  94. get_pkg_namespace <- function(fn) {
  95. x <- names(purrr::keep(regexFn_choices, ~ (fn %in% .)))
  96. if (length(x) > 1) warning(fn, " matches multiple functions in regexFn_choices, please review.")
  97. x
  98. }
  99. #' Check if an updated version is available
  100. #'
  101. #' I included this because it can be difficult to tell if your RStudio Addins
  102. #' are up to date. I may add new features that you want but you won't hear about
  103. #' the updates. This function checks if an update is available, using GitHub
  104. #' tags. If an update is available, a modal dialog is shown when you start
  105. #' the regexplain gadget. This only happens once per R session, though, so feel
  106. #' free to ignore the message.
  107. #'
  108. #' @param gh_user GitHub user account
  109. #' @param gh_repo GitHub repo name
  110. #' @param this_version The currently installed version of the package
  111. #' @keywords internal
  112. check_version <- function(
  113. gh_user = "gadenbuie",
  114. gh_repo = "regexplain",
  115. this_version = packageVersion('regexplain')
  116. ) {
  117. ok_to_check <- getOption("regexplain.no.check.version", TRUE)
  118. if (!isTRUE(ok_to_check)) return(NULL)
  119. if (!requireNamespace('jsonlite', quietly = TRUE)) return(NULL)
  120. get_json <- purrr::possibly(jsonlite::fromJSON, NULL)
  121. gh_tags <- get_json(
  122. paste0("https://api.github.com/repos/", gh_user, "/", gh_repo, "/git/refs/tags"),
  123. simplifyDataFrame = TRUE
  124. )
  125. if (!is.null(gh_tags)) {
  126. gh_tags$tag <- sub("refs/tags/", "", gh_tags$ref, fixed = TRUE)
  127. gh_tags$version <- sub("^v\\.?", "", gh_tags$tag)
  128. }
  129. if (!is.null(gh_tags) && any(gh_tags$version > this_version)) {
  130. max_version <- max(gh_tags$version)
  131. max_tag <- gh_tags$tag[gh_tags$version == max_version]
  132. options(regexplain.no.check.version = FALSE)
  133. return(
  134. list(
  135. version = max_version,
  136. link = paste("https://github.com", gh_user, gh_repo, "releases/tag", max_tag, sep = "/")
  137. )
  138. )
  139. } else return(NULL)
  140. }
  141. #' Loads Regex Pattern Library
  142. #'
  143. #' Patterns sourced from [Regex Hub](https://projects.lukehaas.me/regexhub)
  144. #' are available at <https://github.com/lukehaas/RegexHub> and are copyright
  145. #' Luke Haas licensed under the MIT license available at
  146. #' <https://github.com/lukehaas/RegexHub/commit/3ab87b5a4fd2817b42e2e45dcf040d4f0164ea37>.
  147. #' Patterns source from [qdapRegex](https://github.com/trinker/qdapRegex) are
  148. #' copyright Tyler Rinker and Jason Gray, licensed under the GPL-2 license.
  149. #'
  150. #' @keywords internal
  151. get_regex_library <- function() {
  152. if (!requireNamespace("jsonlite")) {
  153. warning("Please install the `jsonlite` package to use template features")
  154. return(NULL)
  155. }
  156. f_patterns <- system.file("extdata", "patterns.json", package = "regexplain")
  157. if (!file.exists(f_patterns)) return(NULL)
  158. patterns <- jsonlite::fromJSON(
  159. f_patterns,
  160. simplifyVector = FALSE,
  161. simplifyDataFrame = FALSE,
  162. simplifyMatrix = FALSE
  163. )
  164. patterns <- purrr::keep(patterns, ~ .$name != "")
  165. patterns[order(purrr::map_chr(patterns, 'name'))]
  166. }