123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326 |
- /*
- Language: Crystal
- Author: TSUYUSATO Kitsune <make.just.on@gmail.com>
- Website: https://crystal-lang.org
- */
- /** @type LanguageFn */
- function crystal(hljs) {
- const INT_SUFFIX = '(_?[ui](8|16|32|64|128))?';
- const FLOAT_SUFFIX = '(_?f(32|64))?';
- const CRYSTAL_IDENT_RE = '[a-zA-Z_]\\w*[!?=]?';
- const CRYSTAL_METHOD_RE = '[a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|[=!]~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~|]|//|//=|&[-+*]=?|&\\*\\*|\\[\\][=?]?';
- const CRYSTAL_PATH_RE = '[A-Za-z_]\\w*(::\\w+)*(\\?|!)?';
- const CRYSTAL_KEYWORDS = {
- $pattern: CRYSTAL_IDENT_RE,
- keyword:
- 'abstract alias annotation as as? asm begin break case class def do else elsif end ensure enum extend for fun if ' +
- 'include instance_sizeof is_a? lib macro module next nil? of out pointerof private protected rescue responds_to? ' +
- 'return require select self sizeof struct super then type typeof union uninitialized unless until verbatim when while with yield ' +
- '__DIR__ __END_LINE__ __FILE__ __LINE__',
- literal: 'false nil true'
- };
- const SUBST = {
- className: 'subst',
- begin: /#\{/,
- end: /\}/,
- keywords: CRYSTAL_KEYWORDS
- };
- const EXPANSION = {
- className: 'template-variable',
- variants: [
- {
- begin: '\\{\\{',
- end: '\\}\\}'
- },
- {
- begin: '\\{%',
- end: '%\\}'
- }
- ],
- keywords: CRYSTAL_KEYWORDS
- };
- function recursiveParen(begin, end) {
- const
- contains = [
- {
- begin: begin,
- end: end
- }
- ];
- contains[0].contains = contains;
- return contains;
- }
- const STRING = {
- className: 'string',
- contains: [
- hljs.BACKSLASH_ESCAPE,
- SUBST
- ],
- variants: [
- {
- begin: /'/,
- end: /'/
- },
- {
- begin: /"/,
- end: /"/
- },
- {
- begin: /`/,
- end: /`/
- },
- {
- begin: '%[Qwi]?\\(',
- end: '\\)',
- contains: recursiveParen('\\(', '\\)')
- },
- {
- begin: '%[Qwi]?\\[',
- end: '\\]',
- contains: recursiveParen('\\[', '\\]')
- },
- {
- begin: '%[Qwi]?\\{',
- end: /\}/,
- contains: recursiveParen(/\{/, /\}/)
- },
- {
- begin: '%[Qwi]?<',
- end: '>',
- contains: recursiveParen('<', '>')
- },
- {
- begin: '%[Qwi]?\\|',
- end: '\\|'
- },
- {
- begin: /<<-\w+$/,
- end: /^\s*\w+$/
- }
- ],
- relevance: 0
- };
- const Q_STRING = {
- className: 'string',
- variants: [
- {
- begin: '%q\\(',
- end: '\\)',
- contains: recursiveParen('\\(', '\\)')
- },
- {
- begin: '%q\\[',
- end: '\\]',
- contains: recursiveParen('\\[', '\\]')
- },
- {
- begin: '%q\\{',
- end: /\}/,
- contains: recursiveParen(/\{/, /\}/)
- },
- {
- begin: '%q<',
- end: '>',
- contains: recursiveParen('<', '>')
- },
- {
- begin: '%q\\|',
- end: '\\|'
- },
- {
- begin: /<<-'\w+'$/,
- end: /^\s*\w+$/
- }
- ],
- relevance: 0
- };
- const REGEXP = {
- begin: '(?!%\\})(' + hljs.RE_STARTERS_RE + '|\\n|\\b(case|if|select|unless|until|when|while)\\b)\\s*',
- keywords: 'case if select unless until when while',
- contains: [
- {
- className: 'regexp',
- contains: [
- hljs.BACKSLASH_ESCAPE,
- SUBST
- ],
- variants: [
- {
- begin: '//[a-z]*',
- relevance: 0
- },
- {
- begin: '/(?!\\/)',
- end: '/[a-z]*'
- }
- ]
- }
- ],
- relevance: 0
- };
- const REGEXP2 = {
- className: 'regexp',
- contains: [
- hljs.BACKSLASH_ESCAPE,
- SUBST
- ],
- variants: [
- {
- begin: '%r\\(',
- end: '\\)',
- contains: recursiveParen('\\(', '\\)')
- },
- {
- begin: '%r\\[',
- end: '\\]',
- contains: recursiveParen('\\[', '\\]')
- },
- {
- begin: '%r\\{',
- end: /\}/,
- contains: recursiveParen(/\{/, /\}/)
- },
- {
- begin: '%r<',
- end: '>',
- contains: recursiveParen('<', '>')
- },
- {
- begin: '%r\\|',
- end: '\\|'
- }
- ],
- relevance: 0
- };
- const ATTRIBUTE = {
- className: 'meta',
- begin: '@\\[',
- end: '\\]',
- contains: [
- hljs.inherit(hljs.QUOTE_STRING_MODE, {
- className: 'meta-string'
- })
- ]
- };
- const CRYSTAL_DEFAULT_CONTAINS = [
- EXPANSION,
- STRING,
- Q_STRING,
- REGEXP2,
- REGEXP,
- ATTRIBUTE,
- hljs.HASH_COMMENT_MODE,
- {
- className: 'class',
- beginKeywords: 'class module struct',
- end: '$|;',
- illegal: /=/,
- contains: [
- hljs.HASH_COMMENT_MODE,
- hljs.inherit(hljs.TITLE_MODE, {
- begin: CRYSTAL_PATH_RE
- }),
- { // relevance booster for inheritance
- begin: '<'
- }
- ]
- },
- {
- className: 'class',
- beginKeywords: 'lib enum union',
- end: '$|;',
- illegal: /=/,
- contains: [
- hljs.HASH_COMMENT_MODE,
- hljs.inherit(hljs.TITLE_MODE, {
- begin: CRYSTAL_PATH_RE
- })
- ]
- },
- {
- beginKeywords: 'annotation',
- end: '$|;',
- illegal: /=/,
- contains: [
- hljs.HASH_COMMENT_MODE,
- hljs.inherit(hljs.TITLE_MODE, {
- begin: CRYSTAL_PATH_RE
- })
- ],
- relevance: 2
- },
- {
- className: 'function',
- beginKeywords: 'def',
- end: /\B\b/,
- contains: [
- hljs.inherit(hljs.TITLE_MODE, {
- begin: CRYSTAL_METHOD_RE,
- endsParent: true
- })
- ]
- },
- {
- className: 'function',
- beginKeywords: 'fun macro',
- end: /\B\b/,
- contains: [
- hljs.inherit(hljs.TITLE_MODE, {
- begin: CRYSTAL_METHOD_RE,
- endsParent: true
- })
- ],
- relevance: 2
- },
- {
- className: 'symbol',
- begin: hljs.UNDERSCORE_IDENT_RE + '(!|\\?)?:',
- relevance: 0
- },
- {
- className: 'symbol',
- begin: ':',
- contains: [
- STRING,
- {
- begin: CRYSTAL_METHOD_RE
- }
- ],
- relevance: 0
- },
- {
- className: 'number',
- variants: [
- {
- begin: '\\b0b([01_]+)' + INT_SUFFIX
- },
- {
- begin: '\\b0o([0-7_]+)' + INT_SUFFIX
- },
- {
- begin: '\\b0x([A-Fa-f0-9_]+)' + INT_SUFFIX
- },
- {
- begin: '\\b([1-9][0-9_]*[0-9]|[0-9])(\\.[0-9][0-9_]*)?([eE]_?[-+]?[0-9_]*)?' + FLOAT_SUFFIX + '(?!_)'
- },
- {
- begin: '\\b([1-9][0-9_]*|0)' + INT_SUFFIX
- }
- ],
- relevance: 0
- }
- ];
- SUBST.contains = CRYSTAL_DEFAULT_CONTAINS;
- EXPANSION.contains = CRYSTAL_DEFAULT_CONTAINS.slice(1); // without EXPANSION
- return {
- name: 'Crystal',
- aliases: [ 'cr' ],
- keywords: CRYSTAL_KEYWORDS,
- contains: CRYSTAL_DEFAULT_CONTAINS
- };
- }
- module.exports = crystal;
|