123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387 |
- /**
- * @param {string} value
- * @returns {RegExp}
- * */
- /**
- * @param {RegExp | string } re
- * @returns {string}
- */
- function source(re) {
- if (!re) return null;
- if (typeof re === "string") return re;
- return re.source;
- }
- /**
- * @param {RegExp | string } re
- * @returns {string}
- */
- function lookahead(re) {
- return concat('(?=', re, ')');
- }
- /**
- * @param {...(RegExp | string) } args
- * @returns {string}
- */
- function concat(...args) {
- const joined = args.map((x) => source(x)).join("");
- return joined;
- }
- /*
- Language: Ruby
- Description: Ruby is a dynamic, open source programming language with a focus on simplicity and productivity.
- Website: https://www.ruby-lang.org/
- Author: Anton Kovalyov <anton@kovalyov.net>
- Contributors: Peter Leonov <gojpeg@yandex.ru>, Vasily Polovnyov <vast@whiteants.net>, Loren Segal <lsegal@soen.ca>, Pascal Hurni <phi@ruby-reactive.org>, Cedric Sohrauer <sohrauer@googlemail.com>
- Category: common
- */
- function ruby(hljs) {
- const RUBY_METHOD_RE = '([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)';
- const RUBY_KEYWORDS = {
- keyword:
- 'and then defined module in return redo if BEGIN retry end for self when ' +
- 'next until do begin unless END rescue else break undef not super class case ' +
- 'require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor ' +
- '__FILE__',
- built_in: 'proc lambda',
- literal:
- 'true false nil'
- };
- const YARDOCTAG = {
- className: 'doctag',
- begin: '@[A-Za-z]+'
- };
- const IRB_OBJECT = {
- begin: '#<',
- end: '>'
- };
- const COMMENT_MODES = [
- hljs.COMMENT(
- '#',
- '$',
- {
- contains: [ YARDOCTAG ]
- }
- ),
- hljs.COMMENT(
- '^=begin',
- '^=end',
- {
- contains: [ YARDOCTAG ],
- relevance: 10
- }
- ),
- hljs.COMMENT('^__END__', '\\n$')
- ];
- const SUBST = {
- className: 'subst',
- begin: /#\{/,
- end: /\}/,
- keywords: RUBY_KEYWORDS
- };
- const STRING = {
- className: 'string',
- contains: [
- hljs.BACKSLASH_ESCAPE,
- SUBST
- ],
- variants: [
- {
- begin: /'/,
- end: /'/
- },
- {
- begin: /"/,
- end: /"/
- },
- {
- begin: /`/,
- end: /`/
- },
- {
- begin: /%[qQwWx]?\(/,
- end: /\)/
- },
- {
- begin: /%[qQwWx]?\[/,
- end: /\]/
- },
- {
- begin: /%[qQwWx]?\{/,
- end: /\}/
- },
- {
- begin: /%[qQwWx]?</,
- end: />/
- },
- {
- begin: /%[qQwWx]?\//,
- end: /\//
- },
- {
- begin: /%[qQwWx]?%/,
- end: /%/
- },
- {
- begin: /%[qQwWx]?-/,
- end: /-/
- },
- {
- begin: /%[qQwWx]?\|/,
- end: /\|/
- },
- // in the following expressions, \B in the beginning suppresses recognition of ?-sequences
- // where ? is the last character of a preceding identifier, as in: `func?4`
- {
- begin: /\B\?(\\\d{1,3})/
- },
- {
- begin: /\B\?(\\x[A-Fa-f0-9]{1,2})/
- },
- {
- begin: /\B\?(\\u\{?[A-Fa-f0-9]{1,6}\}?)/
- },
- {
- begin: /\B\?(\\M-\\C-|\\M-\\c|\\c\\M-|\\M-|\\C-\\M-)[\x20-\x7e]/
- },
- {
- begin: /\B\?\\(c|C-)[\x20-\x7e]/
- },
- {
- begin: /\B\?\\?\S/
- },
- { // heredocs
- begin: /<<[-~]?'?(\w+)\n(?:[^\n]*\n)*?\s*\1\b/,
- returnBegin: true,
- contains: [
- {
- begin: /<<[-~]?'?/
- },
- hljs.END_SAME_AS_BEGIN({
- begin: /(\w+)/,
- end: /(\w+)/,
- contains: [
- hljs.BACKSLASH_ESCAPE,
- SUBST
- ]
- })
- ]
- }
- ]
- };
- // Ruby syntax is underdocumented, but this grammar seems to be accurate
- // as of version 2.7.2 (confirmed with (irb and `Ripper.sexp(...)`)
- // https://docs.ruby-lang.org/en/2.7.0/doc/syntax/literals_rdoc.html#label-Numbers
- const decimal = '[1-9](_?[0-9])*|0';
- const digits = '[0-9](_?[0-9])*';
- const NUMBER = {
- className: 'number',
- relevance: 0,
- variants: [
- // decimal integer/float, optionally exponential or rational, optionally imaginary
- {
- begin: `\\b(${decimal})(\\.(${digits}))?([eE][+-]?(${digits})|r)?i?\\b`
- },
- // explicit decimal/binary/octal/hexadecimal integer,
- // optionally rational and/or imaginary
- {
- begin: "\\b0[dD][0-9](_?[0-9])*r?i?\\b"
- },
- {
- begin: "\\b0[bB][0-1](_?[0-1])*r?i?\\b"
- },
- {
- begin: "\\b0[oO][0-7](_?[0-7])*r?i?\\b"
- },
- {
- begin: "\\b0[xX][0-9a-fA-F](_?[0-9a-fA-F])*r?i?\\b"
- },
- // 0-prefixed implicit octal integer, optionally rational and/or imaginary
- {
- begin: "\\b0(_?[0-7])+r?i?\\b"
- }
- ]
- };
- const PARAMS = {
- className: 'params',
- begin: '\\(',
- end: '\\)',
- endsParent: true,
- keywords: RUBY_KEYWORDS
- };
- const RUBY_DEFAULT_CONTAINS = [
- STRING,
- {
- className: 'class',
- beginKeywords: 'class module',
- end: '$|;',
- illegal: /=/,
- contains: [
- hljs.inherit(hljs.TITLE_MODE, {
- begin: '[A-Za-z_]\\w*(::\\w+)*(\\?|!)?'
- }),
- {
- begin: '<\\s*',
- contains: [
- {
- begin: '(' + hljs.IDENT_RE + '::)?' + hljs.IDENT_RE,
- // we already get points for <, we don't need poitns
- // for the name also
- relevance: 0
- }
- ]
- }
- ].concat(COMMENT_MODES)
- },
- {
- className: 'function',
- // def method_name(
- // def method_name;
- // def method_name (end of line)
- begin: concat(/def\s+/, lookahead(RUBY_METHOD_RE + "\\s*(\\(|;|$)")),
- relevance: 0, // relevance comes from kewords
- keywords: "def",
- end: '$|;',
- contains: [
- hljs.inherit(hljs.TITLE_MODE, {
- begin: RUBY_METHOD_RE
- }),
- PARAMS
- ].concat(COMMENT_MODES)
- },
- {
- // swallow namespace qualifiers before symbols
- begin: hljs.IDENT_RE + '::'
- },
- {
- className: 'symbol',
- begin: hljs.UNDERSCORE_IDENT_RE + '(!|\\?)?:',
- relevance: 0
- },
- {
- className: 'symbol',
- begin: ':(?!\\s)',
- contains: [
- STRING,
- {
- begin: RUBY_METHOD_RE
- }
- ],
- relevance: 0
- },
- NUMBER,
- {
- // negative-look forward attemps to prevent false matches like:
- // @ident@ or $ident$ that might indicate this is not ruby at all
- className: "variable",
- begin: '(\\$\\W)|((\\$|@@?)(\\w+))(?=[^@$?])' + `(?![A-Za-z])(?![@$?'])`
- },
- {
- className: 'params',
- begin: /\|/,
- end: /\|/,
- relevance: 0, // this could be a lot of things (in other languages) other than params
- keywords: RUBY_KEYWORDS
- },
- { // regexp container
- begin: '(' + hljs.RE_STARTERS_RE + '|unless)\\s*',
- keywords: 'unless',
- contains: [
- {
- className: 'regexp',
- contains: [
- hljs.BACKSLASH_ESCAPE,
- SUBST
- ],
- illegal: /\n/,
- variants: [
- {
- begin: '/',
- end: '/[a-z]*'
- },
- {
- begin: /%r\{/,
- end: /\}[a-z]*/
- },
- {
- begin: '%r\\(',
- end: '\\)[a-z]*'
- },
- {
- begin: '%r!',
- end: '![a-z]*'
- },
- {
- begin: '%r\\[',
- end: '\\][a-z]*'
- }
- ]
- }
- ].concat(IRB_OBJECT, COMMENT_MODES),
- relevance: 0
- }
- ].concat(IRB_OBJECT, COMMENT_MODES);
- SUBST.contains = RUBY_DEFAULT_CONTAINS;
- PARAMS.contains = RUBY_DEFAULT_CONTAINS;
- // >>
- // ?>
- const SIMPLE_PROMPT = "[>?]>";
- // irb(main):001:0>
- const DEFAULT_PROMPT = "[\\w#]+\\(\\w+\\):\\d+:\\d+>";
- const RVM_PROMPT = "(\\w+-)?\\d+\\.\\d+\\.\\d+(p\\d+)?[^\\d][^>]+>";
- const IRB_DEFAULT = [
- {
- begin: /^\s*=>/,
- starts: {
- end: '$',
- contains: RUBY_DEFAULT_CONTAINS
- }
- },
- {
- className: 'meta',
- begin: '^(' + SIMPLE_PROMPT + "|" + DEFAULT_PROMPT + '|' + RVM_PROMPT + ')(?=[ ])',
- starts: {
- end: '$',
- contains: RUBY_DEFAULT_CONTAINS
- }
- }
- ];
- COMMENT_MODES.unshift(IRB_OBJECT);
- return {
- name: 'Ruby',
- aliases: [
- 'rb',
- 'gemspec',
- 'podspec',
- 'thor',
- 'irb'
- ],
- keywords: RUBY_KEYWORDS,
- illegal: /\/\*/,
- contains: [
- hljs.SHEBANG({
- binary: "ruby"
- })
- ]
- .concat(IRB_DEFAULT)
- .concat(COMMENT_MODES)
- .concat(RUBY_DEFAULT_CONTAINS)
- };
- }
- module.exports = ruby;
|