🔍 An RStudio addin slash regex utility belt
Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

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. }