🔍 An RStudio addin slash regex utility belt
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

168 lines
4.7KB

  1. #' regexplain_addin
  2. #'
  3. #' @keywords internal
  4. regexplain_addin <- function() {
  5. # Get the document context.
  6. context <- rstudioapi::getActiveDocumentContext()
  7. # Get context text
  8. ctx_text <- context$selection[[1]]$text
  9. # If it is one line and evaluates to something, use that
  10. # Otherwise treat as text
  11. obj <- tryCatch({
  12. if (grepl("\n", ctx_text)) {
  13. ctx_text
  14. } else {
  15. x <- eval(parse(text = ctx_text))
  16. x <- as.character(x)
  17. if (length(x) == 1 && grepl("\n", x))
  18. x <- strsplit(x, "\n")[[1]]
  19. if (length(x) > 10) {
  20. message(ctx_text, " gave ", length(x), " lines, limiting to first 10 unique lines.")
  21. x <- unique(x)
  22. x[1:min(length(x), 10)]
  23. } else x
  24. }
  25. },
  26. error = function(e) {as.character(ctx_text)})
  27. regex_gadget(obj)
  28. }
  29. #' regexplain gadget
  30. #'
  31. #' @import miniUI
  32. #' @import shiny
  33. #' @export
  34. regex_gadget <- function(text = NULL) {
  35. stopifnot(requireNamespace("miniUI"), requireNamespace("shiny"))
  36. ui <- miniPage(
  37. shiny::includeCSS(system.file("style.css", package = "regexplain")),
  38. gadgetTitleBar(
  39. "regexplain",
  40. right = miniTitleBarButton("done", "To Console", TRUE)
  41. ),
  42. miniTabstripPanel(
  43. selected = if (is.null(text)) "Text" else "Regex",
  44. miniTabPanel(
  45. "Text", icon = icon('file-text-o'),
  46. miniContentPanel(
  47. fillCol(
  48. textAreaInputAlt('text', label = "Text", value = paste(text, collapse = "\n"), resize = "both", width = "100%", height="90%")
  49. )
  50. )
  51. ),
  52. miniTabPanel(
  53. "Regex", icon = icon('terminal'),
  54. miniContentPanel(
  55. fillCol(
  56. flex = c(1, 3),
  57. fillRow(
  58. flex = c(2, 1),
  59. textInputCode('pattern', 'Regex', width = "90%",
  60. placeholder = "Enter regex, single \\ okay"),
  61. checkboxGroupInput(
  62. 'regex_options',
  63. label = "",
  64. inline = TRUE,
  65. width = "90%",
  66. choices = c("Break Lines" = "text_break_lines",
  67. "Ignore Case" = "ignore.case",
  68. "Perl Style" = "perl",
  69. "Fixed" = "fixed",
  70. "Use Bytes" = "useBytes"
  71. # , "Invert" = "invert"
  72. ),
  73. selected = c('text_break_lines')
  74. )
  75. ),
  76. htmlOutput('result')
  77. )
  78. )
  79. ),
  80. miniTabPanel(
  81. "Output", icon = icon("table"),
  82. miniContentPanel(
  83. tags$p("Test output of regex on text here.")
  84. )
  85. ),
  86. miniTabPanel(
  87. "Help", icon = icon("support"),
  88. miniContentPanel(
  89. tags$p("Help will go here.")
  90. )
  91. )
  92. )
  93. )
  94. server <- function(input, output, session) {
  95. rtext <- reactive({
  96. x <- if ('text_break_lines' %in% input$regex_options) {
  97. strsplit(input$text, "\n")[[1]]
  98. } else input$text
  99. x
  100. })
  101. output$result <- renderUI({
  102. if (is.null(rtext())) return(NULL)
  103. if (input$pattern == "") {
  104. return(toHTML(paste('<p class="results">', escape_html(rtext()), "</p>", collapse = "")))
  105. }
  106. tryCatch({
  107. toHTML(
  108. paste(
  109. view_regex(
  110. rtext(),
  111. sanitize_text_input(input$pattern),
  112. ignore.case = 'ignore.case' %in% input$regex_options,
  113. perl = 'perl' %in% input$regex_options,
  114. fixed = 'fixed' %in% input$regex_options,
  115. useBytes = 'useBytes' %in% input$regex_options,
  116. # invert = 'invert' %in% input$regex_options,
  117. render = FALSE,
  118. escape = TRUE),
  119. collapse = ""
  120. )
  121. )
  122. },
  123. error = function(e) {
  124. toHTML(paste0("<pre class='alert alert-danger' style='padding: 4px; margin-top: 1px; margin-bottom: 4px;'>", paste(e$message, collapse = "<br>"), "</pre>"),
  125. paste('<p class="results">', escape_html(rtext()), "</p>", collapse = ""))
  126. })
  127. })
  128. observeEvent(input$done, {
  129. # browser()
  130. if (input$pattern != "") {
  131. pattern <- paste0('regex <- "', escape_backslash(sanitize_text_input(input$pattern)), '"')
  132. rstudioapi::sendToConsole(pattern, FALSE)
  133. }
  134. stopApp()
  135. })
  136. observeEvent(input$cancel, {
  137. stopApp()
  138. })
  139. }
  140. viewer <- shiny::paneViewer(700)
  141. runGadget(ui, server, viewer = viewer)
  142. }
  143. sanitize_text_input <- function(x) {
  144. x <- gsub("(“|”)", '"', x)
  145. x <- gsub("‘|’", "'", x)
  146. x
  147. }
  148. toHTML <- function(...) {
  149. x <- paste(..., collapse = "")
  150. x <- gsub("\n", "\\\\n", x)
  151. x <- gsub("\t", "\\\\t", x)
  152. x <- gsub("\r", "\\\\r", x)
  153. HTML(x)
  154. }