简体   繁体   中英

Highlighting in ACE editor that is embedded in R Shiny

I try to highlight a set of words in the ace-editor that is embedded in an R Shiny app. I followed suggestions from Want to highlight/change color of certain words in Ace Editor? , but highlighting does not work when the aceEditor() function is used, which I need for my app. However, if I replace the aceEditor() function with a tags$body command (see below), highlighting works. Please see my code below. My question: Is there a way to use highlighting with the aceEditor() function?

Here is an example in which the word Mark should appear in blue.

Use of aceEditor() , which fails:

library(shiny)
library(shinyAce)

htmlScript = "<script>\n define('ace/mode/custom', [], function(require, exports, module) {\n var oop = require(\"ace/lib/oop\");\n var TextMode = require(\"ace/mode/text\").Mode;"
htmlScript = paste0(htmlScript,"\n var Tokenizer = require(\"ace/tokenizer\").Tokenizer;\n var CustomHighlightRules = require(\"ace/mode/custom_highlight_rules\").CustomHighlightRules;")
htmlScript = paste0(htmlScript,"\n\n var Mode = function() {\n this.HighlightRules = CustomHighlightRules;\n};\n oop.inherits(Mode, TextMode);\n\n (function() {\n\n}).call(Mode.prototype);\n\n exports.Mode = Mode;\n});")
htmlScript = paste0(htmlScript,"\n define('ace/mode/custom_highlight_rules', [], function(require, exports, module) {\n var oop = require(\"ace/lib/oop\");\n var TextHighlightRules = require(\"ace/mode/text_highlight_rules\").TextHighlightRules;\n")
htmlScript = paste0(htmlScript,"\n var CustomHighlightRules = function() {\n\n var keywordMapper = this.createKeywordMapper({\n \"variable.language\": \"this\",\n \"keyword\": \"Mark|Ben|Bill\",\n \"constant.language\": \"true|false|null\",\n \"customTokenName\": \"problem\"\n}, \"text\", true);\n")
htmlScript = paste0(htmlScript,"\n this.$rules = {\n\"start\": [\n{\nregex: \"\\\\w+\\\\b\",\n token: keywordMapper\n},\n]\n};\n this.normalizeRules()\n};\n\n oop.inherits(CustomHighlightRules, TextHighlightRules);\n\n")
htmlScript = paste0(htmlScript,"\nexports.CustomHighlightRules = CustomHighlightRules;\n});\n\nvar editor = ace.edit(\"editor\");\n\n editor.session.setMode(\"ace/mode/custom\");\n</script>")
  
ui <- fluidPage(
  tags$head(HTML("<script src=\"https://ajaxorg.github.io/ace-builds/src/ace.js\"></script>")),

  aceEditor("editor", value="Mark", mode = "text"), #Mark should be highlighted with blue color

  tags$body(HTML(htmlScript))
)

server <- function(input, output, session){}

shinyApp(ui, server)

Use of tags$body command, which works:

ui <- fluidPage(
  tags$head(HTML("<script src=\"https://ajaxorg.github.io/ace-builds/src/ace.js\"></script>")),

  tags$body(HTML("<div id=\"editor\" style=\"height: 500px; width: 800px\"></div>")),

  tags$body(HTML(htmlScript))
)

server <- function(input, output, session){}

shinyApp(ui, server)

Please type the word Mark in the editor, it will appear in blue.

shinyAce wraps the calls to the ace libraries. In particular the mode which defines the syntax highlighting. I am not an expert in JavaScript , hence, I do not know where and how aceEditor overrules your manual settings, but I know enough to know how you could get your custom style working.

  1. Create a .js file with the following content:

     ace.define('ace/mode/custom', [], function(require, exports, module) { var oop = require("ace/lib/oop"); var TextMode = require("ace/mode/text").Mode; var Tokenizer = require("ace/tokenizer").Tokenizer; var CustomHighlightRules = require("ace/mode/custom_highlight_rules").CustomHighlightRules; var Mode = function() { this.HighlightRules = CustomHighlightRules; }; oop.inherits(Mode, TextMode); (function() { }).call(Mode.prototype); exports.Mode = Mode; }); ace.define('ace/mode/custom_highlight_rules', [], function(require, exports, module) { var oop = require("ace/lib/oop"); var TextHighlightRules = require("ace/mode/text_highlight_rules").TextHighlightRules; var CustomHighlightRules = function() { var keywordMapper = this.createKeywordMapper({ "variable.language": "this", "keyword": "Mark|Ben|Bill", "constant.language": "true|false|null", "customTokenName": "problem" }, "text", true); this.$rules = { "start": [{ regex: "\\w+\\b", token: keywordMapper }, ] }; this.normalizeRules() }; oop.inherits(CustomHighlightRules, TextHighlightRules); exports.CustomHighlightRules = CustomHighlightRules; });

    Note in particular the use of ace.define instead of define .

  2. Place the file in the folder shown by

    system.file("www/ace", package = "shinyAce")

    under the name mode-custom.js .

  3. Then you are set and the following code highlights Mark correctly:

     library(shiny) library(shinyAce) ui <- fluidPage( aceEditor("editor", value = "Mark", mode = "custom") ) server <- function(input, output, session){} shinyApp(ui, server)

    自定义语法高亮


Update

Actually you do not need to store the js in the lib folder, but define it on the spot. Just make suere that you use ace.define nad you use the name of the mode in aceEditor :

library(shiny)
library(shinyAce)

htmlScript = "<script>\n ace.define('ace/mode/custom', [], function(require, exports, module) {\n var oop = require(\"ace/lib/oop\");\n var TextMode = require(\"ace/mode/text\").Mode;"
htmlScript = paste0(htmlScript,"\n var Tokenizer = require(\"ace/tokenizer\").Tokenizer;\n var CustomHighlightRules = require(\"ace/mode/custom_highlight_rules\").CustomHighlightRules;")
htmlScript = paste0(htmlScript,"\n\n var Mode = function() {\n this.HighlightRules = CustomHighlightRules;\n};\n oop.inherits(Mode, TextMode);\n\n (function() {\n\n}).call(Mode.prototype);\n\n exports.Mode = Mode;\n});")
htmlScript = paste0(htmlScript,"\n ace.define('ace/mode/custom_highlight_rules', [], function(require, exports, module) {\n var oop = require(\"ace/lib/oop\");\n var TextHighlightRules = require(\"ace/mode/text_highlight_rules\").TextHighlightRules;\n")
htmlScript = paste0(htmlScript,"\n var CustomHighlightRules = function() {\n\n var keywordMapper = this.createKeywordMapper({\n \"variable.language\": \"this\",\n \"keyword\": \"Mark|Ben|Bill|Thorn|ULL\",\n \"constant.language\": \"true|false|null\",\n \"customTokenName\": \"problem\"\n}, \"text\", true);\n")
htmlScript = paste0(htmlScript,"\n this.$rules = {\n\"start\": [\n{\nregex: \"\\\\w+\\\\b\",\n token: keywordMapper\n},\n]\n};\n this.normalizeRules()\n};\n\n oop.inherits(CustomHighlightRules, TextHighlightRules);\n\n")
htmlScript = paste0(htmlScript,"\nexports.CustomHighlightRules = CustomHighlightRules;\n});\n\nvar editor = ace.edit(\"editor\");\n\n editor.session.setMode(\"ace/mode/custom\");\n</script>")
  
ui <- fluidPage(
  aceEditor("editor", value="Mark", mode = "custom"), #Mark should be highlighted with blue color
  tags$body(HTML(htmlScript))
)

server <- function(input, output, session){}

shinyApp(ui, server)
``

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM