🤷‍♂️ RStudio Addin to Search and Copy Emoji
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.

220 lines
7.3KB

  1. #' The ermoji emoji gadget
  2. #'
  3. #' Opens a miniUI based Shiny gadget in the RStudio Viewer pane with a
  4. #' searchable table of emoji. Select a row and click the copy desired button.
  5. #'
  6. #' @param clipout Should the gadget attempt to write to the clipboard?
  7. #' @param ... Ignored at this time
  8. #' @name ermoji
  9. #' @return nothing
  10. #' @export
  11. ermoji_gadget <- function(clipout = clipr::clipr_available(), ...) {
  12. shiny::runGadget(ermoji_ui, ermoji_server(clipout, ...), viewer = shiny::paneViewer(500), stopOnCancel = FALSE)
  13. }
  14. #' @rdname ermoji
  15. #' @export
  16. ermoji_shiny <- function(clipout = clipr::clipr_available(), ...) {
  17. shiny::shinyApp(ui = ermoji_ui, server = ermoji_server(clipout, ...))
  18. }
  19. ermoji_ui <- miniUI::miniPage(
  20. title = "ermoji",
  21. shiny::tags$head(
  22. shiny::tags$style(
  23. shiny::HTML("
  24. .dropdown-item {
  25. display: block;
  26. width: 100%;
  27. padding: .25rem 1.5rem;
  28. clear: both;
  29. font-weight: 400;
  30. color: #212529;
  31. text-align: inherit;
  32. white-space: nowrap;
  33. background-color: transparent;
  34. border: 0;
  35. }
  36. .dropdown-menu {
  37. color: #212529;
  38. text-align: left;
  39. list-style: none;
  40. }
  41. @media (min-height: 600px) {
  42. td.big { font-size: 2em; }
  43. }
  44. @media (max-height: 599px) {
  45. td.big { font-size: 1.5em; }
  46. }
  47. table.dataTable tbody td {
  48. vertical-align: middle;
  49. }
  50. ")
  51. )
  52. ),
  53. miniUI::gadgetTitleBar("ermoji"),
  54. miniUI::miniContentPanel(
  55. padding = 10,
  56. DT::dataTableOutput('emojis', height = "100%", width = "98%")
  57. ),
  58. miniUI::miniButtonBlock(
  59. shiny::actionButton("copy_name", "Copy :emoji_name:", class = "btn-success"),
  60. shiny::tags$div(class = "btn-group dropup", style = "width: 33%",
  61. shiny::tags$button(class = "btn btn-warning dropdown-toggle", href = "#",
  62. role = "button", id = "dropdownMenuLink", style = "width: 100%",
  63. "data-toggle" = "dropdown", "aria-haspopup" = "true",
  64. "aria-expanded" = "false",
  65. "Copy Unicode"),
  66. shiny::tags$div(class = "dropdown-menu", style = "width: 100%",
  67. "aria-labelledby"="dropdownMenuLink",
  68. shiny::actionLink("copy_utf", "Copy unicode", class = "dropdown-item"),
  69. shiny::actionLink("copy_html", "Copy HTML", class = "dropdown-item")
  70. )
  71. ),
  72. shiny::actionButton("copy_gliph", "Copy Emoji", class = "btn-primary")
  73. )
  74. )
  75. ermoji_server <- function(clipout = clipr::clipr_available()) {
  76. function(input, output, session) {
  77. output$emojis <- DT::renderDataTable({
  78. emojis <- emo::jis
  79. emojis <- emojis[, c('emoji', 'name', "group", "keywords", "aliases")]
  80. emojis$group <- factor(emojis$group)
  81. emojis$keywords <- vapply(emojis$keywords, function(x) paste(x, collapse = ", "), character(1))
  82. emojis$aliases <- vapply(emojis$aliases, function(x) paste(x, collapse = ", "), character(1))
  83. DT::datatable(
  84. emojis,
  85. rownames = FALSE,
  86. colnames = c("Emoji", "Name", "Group", "Keywords", "Aliases"),
  87. filter = "top",
  88. selection = "single",
  89. fillContainer = TRUE,
  90. style = 'bootstrap',
  91. class = 'compact stripe hover',
  92. extensions = c("Scroller"),
  93. options = list(
  94. dom = "<'row'<'col-sm-6 col-sm-offset-2 text-center'f>>tir",
  95. searchHighlight = TRUE,
  96. search = list(regex = TRUE, caseInsensitive = FALSE),
  97. autoWidth = FALSE,
  98. columnDefs = list(
  99. list(
  100. className = "dt-center big", searchable = FALSE, width = "10%", targets = 0
  101. ),
  102. list(width = "20%", targets = c(1, 3, 4)),
  103. list(width = "10%", targets = 2)
  104. ),
  105. deferRender = TRUE,
  106. scrollY = 500,
  107. scroller = TRUE
  108. )
  109. )
  110. })
  111. this_emoji <- shiny::reactive({
  112. shiny::req(input$emojis_rows_selected)
  113. as.list(emo::jis[input$emojis_rows_selected, ])
  114. })
  115. this_emoji_name <- shiny::reactive({
  116. # name <- this_emoji()$name
  117. name <- this_emoji()$aliases[[1]][1]
  118. paste0(":", gsub(" ", "_", name), ":")
  119. })
  120. this_emoji_uni <- shiny::reactive({
  121. uni <- paste0("\\U", this_emoji()$runes)
  122. gsub(" ", "\\\\U", uni)
  123. })
  124. this_emoji_html <- shiny::reactive({
  125. rune2html(this_emoji()$runes)
  126. })
  127. truncate <- function(x, n = 10) {
  128. if (nchar(x) > n) {
  129. paste0(strtrim(x, n), "...")
  130. } else x
  131. }
  132. shiny::observeEvent(input$emojis_rows_selected, {
  133. if (!shiny::isTruthy(input$emojis_rows_selected)) {
  134. shiny::updateActionButton(session, "copy_name", "Copy :emoji_name:")
  135. shiny::updateActionButton(session, "copy_utf", "Copy Unicode")
  136. shiny::updateActionButton(session, "copy_html", "Copy HTML")
  137. shiny::updateActionButton(session, "copy_gliph", "Copy Emoji")
  138. } else {
  139. shiny::updateActionButton(session, "copy_name", paste0("Copy <code>", this_emoji_name(), "</code>"))
  140. shiny::updateActionButton(session, "copy_utf", paste("Copy Unicode: <code>", truncate(this_emoji_uni()), "</code>"))
  141. shiny::updateActionButton(session, "copy_html", paste("Copy HTML: <code>", escape_html(truncate(this_emoji_html())), "</code>"))
  142. shiny::updateActionButton(session, "copy_gliph", paste("Copy", this_emoji()$emoji))
  143. }
  144. })
  145. copy_modal <- function(text) {
  146. shiny::showModal(
  147. shiny::modalDialog(
  148. title = "Select and Copy",
  149. shiny::tags$p("I don't have access to your clipboard. Select the text and", shiny::tags$kbd("Ctrl/Cmd"), "+", shiny::tags$kbd("c"), "to copy."),
  150. shiny::tags$pre(text),
  151. easyClose = TRUE
  152. )
  153. )
  154. }
  155. shiny::observeEvent(input$copy_name, {
  156. if (clipout) clipr::write_clip(this_emoji_name()) else copy_modal(this_emoji_name())
  157. })
  158. shiny::observeEvent(input$copy_utf, {
  159. if (clipout) clipr::write_clip(this_emoji_uni()) else copy_modal(this_emoji_uni())
  160. })
  161. shiny::observeEvent(input$copy_html, {
  162. if (clipout) clipr::write_clip(this_emoji_html()) else copy_modal(this_emoji_html())
  163. })
  164. shiny::observeEvent(input$copy_gliph, {
  165. if (clipout) clipr::write_clip(this_emoji()$emoji) else copy_modal(this_emoji()$emoji)
  166. })
  167. shiny::observeEvent(input$done, {
  168. shiny::stopApp(invisible())
  169. })
  170. shiny::observeEvent(input$cancel, {
  171. shiny::stopApp(invisible())
  172. })
  173. }
  174. }
  175. escape_html <- function(x) {
  176. x = gsub('&', '&amp;', x)
  177. x = gsub('<', '&lt;', x)
  178. x = gsub('>', '&gt;', x)
  179. x = gsub('"', '&quot;', x)
  180. x
  181. }
  182. #' Convert Emoji to HTML
  183. #'
  184. #' Uses [emo::ji()] to look up emoji, but return the escaped HTML.
  185. #'
  186. #' @param x A search term passed to [emo::ji()] or the result of [emo::ji()].
  187. #' @param copy Should the result be copied to the clipboard?
  188. #' @export
  189. emoji2html <- function(x, copy = clipr::clipr_available()) {
  190. emojis <- emo::jis$runes
  191. names(emojis) <- emo::jis$emoji
  192. if (!inherits(x, "emoji")) {
  193. x <- emo::ji(x)
  194. }
  195. emoji <- emojis[x]
  196. emoji_html <- rune2html(unname(emoji))
  197. if (copy) {
  198. clipr::write_clip(emoji_html)
  199. message(emoji_html, " copied to clipboard")
  200. return(invisible(emoji_html))
  201. }
  202. emoji_html
  203. }
  204. rune2html <- function(runes) {
  205. gsub("([0-9A-F]{4,8}) ?", "&#x\\1;", runes)
  206. }