Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Visual Studio Code互換なsyntax highlighterの実装

Visual Studio Code互換なsyntax highlighterの実装

omochimetaru

March 01, 2019
Tweet

More Decks by omochimetaru

Other Decks in Programming

Transcript

  1. ۙ೥ͷτϨϯυ • TextMate • Sublime Text • Atom • Visual

    Studio Code ͜ΕΒશ͕ͯTextMateܗࣜΛ࠾༻ 5
  2. 8

  3. 12

  4. { "name": "JSON (Javascript Next)", "scopeName": "source.json", "patterns": [ ],

    "repository": { "array": { }, "comments": { }, "constant": { }, "number": { }, "object": { }, "string": { }, "objectkey": { }, "stringcontent": { }, "value": { } } } 16
  5. { "patterns": [ { "include": "#value" } ], "repository": {

    "array": { }, "comments": { }, "constant": { }, "number": { }, "object": { }, "string": { }, "objectkey": { }, "stringcontent": { }, "value": { "patterns": [ { "include": "#constant" }, { "include": "#number" }, { "include": "#string" }, { "include": "#array" }, { "include": "#object" }, { "include": "#comments" } ] } } } 18
  6. { "repository": { "constant": { "match": "\\b(?:true|false|null)\\b", "name": "constant.language.json" },

    "number": { "match": "(?x) # turn on extended mode\n" " -? # an optional minus\n" " (?:\n" " 0 # a zero\n" " | # ...or...\n" " [1-9] # a 1-9 character\n" " \\d* # followed by zero or more digits\n" " )\n" " (?:\n" " (?:\n" " \\. # a period\n" " \\d+ # followed by one or more digits\n" " )?\n" " (?:\n" " [eE] # an e character\n" " [+-]? # followed by an option +/-\n" " \\d+ # followed by one or more digits\n" " )? # make exponent optional\n" " )? # make decimal portion optional", "name": "constant.numeric.json" }, } } number.match͸දࣔͷ౎߹্෼ׂ͍ͯ͠·͕࣮͢ࡍʹ͸1ͭͷ௕͍จࣈྻͰ͋Δɻ 21
  7. JSONͷ਺஋ͷਖ਼نදݱ (?x) # turn on extended mode -? # an

    optional minus (?: 0 # a zero | # ...or... [1-9] # a 1-9 character \d* # followed by zero or more digits )\n (?: (?: \. # a period \d+ # followed by one or more digits )? (?: [eE] # an e character\n [+-]? # followed by an option +/- \d+ # followed by one or more digits )? # make exponent optional )? # make decimal portion optional ๯಄ͷ(?x)Ͱ֦ுه๏ϞʔυΛ։࢝ͯ͠վߦͱίϝϯτΛ༗ޮԽ 23
  8. { "repository": { "array": { "begin": "\\[", "end": "\\]", "name":

    "meta.structure.array.json", "patterns": [ { "include": "#value" }, { "match": ",", "name": "punctuation.separator.array.json" }, { "match": "[^\\s\\]]", "name": "invalid.illegal.expected-array-separator.json" } ] }, } } 26
  9. JSONจ๏ͰͷϚονϯάϦ ετ rootͷ࣌ • \b(?:true|false|null)\b: root[0]→value[0]→constant.match • (?x)...: root[0]→value[1]→number.match •

    \": root[0]→value[2]→string.begin • \[": root[0]→value[3]→array.begin • \{: root[0]→value[4]→object.begin • /\*\*(?!/): root[0]→value[5]→comments[0] • /\*: root[0]→value[5]→comments[1] • (//).*$\n?: root[0]→value[5]→comments[2] 29
  10. arrayͷ࣌ • \]: array.end • \b(?:true|false|null)\b: array[0]→value[0]→constant.match • (?x)...: array[0]→value[1]→number.match

    • \": array[0]→value[2]→string.begin • \[": array[0]→value[3]→array.begin • \{: array[0]→value[4]→object.begin • /\*\*(?!/): array[0]→value[5]→comments[0] • /\*: array[0]→value[5]→comments[1] • (//).*$\n?: array[0]→value[5]→comments[2] • ,: array[1].match • [^\s\]]: array[2].match 30
  11. HTMLͷߏจͷதͰPHPͷߏจΛݺͿ { "name": "PHP", "scopeName": "text.html.php", "repository": { "php-tag": {

    "patterns": [ { "begin": "<\\?(?i:php|=)?(?![^?]*\\?>)", "end": "(\\?)>", "name": "meta.embedded.block.php", "contentName": "source.php", "patterns": [ { "include": "source.php" } ] }, ] } } } 36
  12. جຊฤ ·ͱΊ • Grammar, Repository, Rule • Hub, Include, Match,

    BeginEnd • ݱࡏͷRule • ϚονϦετͷચ͍ग़͠ • ࠷΋ࠨͰϚονͨ͠ਖ਼نදݱ • ߦ୯Ґॲཧ ࢓૊Έͷࠎ૊Έ͸͜Ε͚ͩ 37
  13. { "captures": { "1": { "name": "support.function.construct.php" }, "2": {

    "name": "punctuation.definition.array.begin.php" }, "3": { "name": "punctuation.definition.array.end.php" } }, "match": "(array)(\\()(\\))", "name": "meta.array.empty.php" } 41
  14. { "array": { "begin": "\\[", "beginCaptures": { "0": { "name":

    "punctuation.definition.array.begin.json" } }, "end": "\\]", "endCaptures": { "0": { "name": "punctuation.definition.array.end.json" } }, "name": "meta.structure.array.json", "patterns": [ ... ] } } 42
  15. { "begin": "(?x)\\s*\n" "\t\t\t\t\t ((?:(?:final|abstract|public|private|protected|static)\\s+)*)\n" "\t\t\t\t (function)\n" "\t\t\t\t (?:\\s+|(\\s*&\\s*))\n" "\t\t\t\t

    (?:\n" "\t\t\t\t (__(?:call|construct|destruct|get|set|isset|unset|tostring|" "clone|set_state|sleep|wakeup|autoload|invoke|callStatic))\n" "\t\t\t\t |([a-zA-Z0-9_]+)\n" "\t\t\t\t )\n" "\t\t\t\t \\s*\n" "\t\t\t\t (\\()", "beginCaptures": { "1": { "patterns": [ { "match": "final|abstract|public|private|protected|static", "name": "storage.modifier.php" } ] }, "2": { "name": "storage.type.function.php" }, "3": { "name": "storage.modifier.reference.php" }, "4": { "name": "support.function.magic.php" }, "5": { "name": "entity.name.function.php" }, "6": { "name": "punctuation.definition.parameters.begin.php" } } } 45
  16. { "begin": "(?><<-(\\w+))", "beginCaptures": { "0": { "name": "punctuation.definition.string.begin.ruby" }

    }, "comment": "heredoc with indented terminator", "end": "\\s*\\1$", "endCaptures": { "0": { "name": "punctuation.definition.string.end.ruby" } }, "name": "string.unquoted.heredoc.ruby", "patterns": [ { "include": "#heredoc" }, { "include": "#interpolated_ruby" }, { "include": "#escaped_char" } ] } 48
  17. { "begin": "(^[ \\t]+)?(?=//)", "beginCaptures": { "1": { "name": "punctuation.whitespace.comment.leading.php"

    } }, "end": "(?!\\G)", "patterns": [ { "begin": "//", "beginCaptures": { "0": { "name": "punctuation.definition.comment.php" } }, "end": "\\n|(?=\\?>)", "name": "comment.line.double-slash.php" } ] } 51
  18. { "string-double-quoted": { "begin": "\"", "beginCaptures": { "0": { "name":

    "punctuation.definition.string.begin.php" } }, "contentName": "meta.string-contents.quoted.double.php", "end": "\"", "endCaptures": { "0": { "name": "punctuation.definition.string.end.php" } }, "name": "string.quoted.double.php", "patterns": [ { "include": "#interpolation" } ] } 54
  19. { "begin": "\\?", "beginCaptures": { "0": { "name": "keyword.operator.ternary.c" }

    }, "end": ":", "applyEndPatternLast": true, "endCaptures": { "0": { "name": "keyword.operator.ternary.c" } }, "patterns": [ { "include": "#access" }, { "include": "#libc" }, { "include": "#c_function_call" }, { "include": "$base" } ] } 57
  20. { "begin": "\\b(require|require_relative|gem)\\b", "captures": { "1": { "name": "keyword.other.special-method.ruby" }

    }, "end": "$|(?=#|\\})", "name": "meta.require.ruby", "patterns": [ { "include": "$self" } ] } 60
  21. { "parens": { "begin": "\\(", "beginCaptures": { "0": { "name":

    "punctuation.section.parens.begin.c" } }, "end": "\\)", "endCaptures": { "0": { "name": "punctuation.section.parens.end.c" } }, "name": "meta.parens.c", "patterns": [ { "include": "$base" } ] } } 63
  22. { "begin": "@\"", "beginCaptures": { "0": { "name": "punctuation.definition.string.begin.objc" }

    }, "end": "\"", "endCaptures": { "0": { "name": "punctuation.definition.string.end.objc" } }, "name": "string.quoted.double.objc", "patterns": [ { "include": "source.c#string_escaped_char" }, { "match": "(?x)%\n" "\t\t\t\t\t\t(\\d+\\$)? # field (argument #)\n" "\t\t\t\t\t\t[#0\\- +']* # flags\n" "\t\t\t\t\t\t((-?\\d+)|\\*(-?\\d+\\$)?)? # minimum field width\n" "\t\t\t\t\t\t(\\.((-?\\d+)|\\*(-?\\d+\\$)?)?)? # precision\n" "\t\t\t\t\t\t[@] # conversion type\n" "\t\t\t\t\t", "name": "constant.other.placeholder.objc" }, { "include": "source.c#string_placeholder" } ] } 66
  23. { "regular_expressions": { "comment": "Changed disabled to 1 to turn

    off syntax highlighting in “r” strings.", "disabled": 0, "patterns": [ { "include": "source.regexp.python" } ] } } 69
  24. { "scopeName": "todo-comment.injection", "injectionSelector": "L:comment.line.double-slash", "patterns": [ { "include": "#todo-keyword"

    } ], "repository": { "todo-keyword": { "match": "TODO", "name": "keyword.todo" } } } 74
  25. { "injectionSelector": "text, string, comment", "name": "Hyperlink", "patterns": [ {

    "match": "(?x)\n" "\t\t\t\t( (https?|s?ftp|ftps|file|smb|afp|nfs|(x-)?man(-page)?|gopher|txmt|issue)://|mailto:)\n" "\t\t\t\t[-:@a-zA-Z0-9_.,~%+/?=&#;]+(?<![-.,?:#;])\n" "\t\t\t", "name": "markup.underline.link.$2.hyperlink" }, { "match": "(?i)\\bRFC(?: |(?<= RFC))(\\d+)\\b", "name": "markup.underline.link.rfc.$1.hyperlink" } ], "scopeName": "text.hyperlink" } 75
  26. { "injections": { "text.html.php - (meta.embedded | meta.tag), " "L:text.html.php

    meta.tag, " "L:source.js.embedded.html": { "patterns": [ { }, { }, { } ] } }, "name": "PHP", "patterns": [ { "include": "text.html.basic" } ], "repository": { } } 77