You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
270 lines
7.2 KiB
270 lines
7.2 KiB
4 years ago
|
/**
|
||
|
* @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) {
|
||
|
var RUBY_METHOD_RE = '([a-zA-Z_]\\w*[!?=]?|[-+~]@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?)';
|
||
|
var 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'
|
||
|
};
|
||
|
var YARDOCTAG = {
|
||
|
className: 'doctag',
|
||
|
begin: '@[A-Za-z]+'
|
||
|
};
|
||
|
var IRB_OBJECT = {
|
||
|
begin: '#<', end: '>'
|
||
|
};
|
||
|
var COMMENT_MODES = [
|
||
|
hljs.COMMENT(
|
||
|
'#',
|
||
|
'$',
|
||
|
{
|
||
|
contains: [YARDOCTAG]
|
||
|
}
|
||
|
),
|
||
|
hljs.COMMENT(
|
||
|
'^=begin',
|
||
|
'^=end',
|
||
|
{
|
||
|
contains: [YARDOCTAG],
|
||
|
relevance: 10
|
||
|
}
|
||
|
),
|
||
|
hljs.COMMENT('^__END__', '\\n$')
|
||
|
];
|
||
|
var SUBST = {
|
||
|
className: 'subst',
|
||
|
begin: /#\{/, end: /\}/,
|
||
|
keywords: RUBY_KEYWORDS
|
||
|
};
|
||
|
var 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: /\|/},
|
||
|
{
|
||
|
// \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}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/
|
||
|
},
|
||
|
{ // heredocs
|
||
|
begin: /<<[-~]?'?(\w+)(?:.|\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
|
||
|
var decimal = '[1-9](_?[0-9])*|0';
|
||
|
var digits = '[0-9](_?[0-9])*';
|
||
|
var 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" },
|
||
|
]
|
||
|
};
|
||
|
|
||
|
var PARAMS = {
|
||
|
className: 'params',
|
||
|
begin: '\\(', end: '\\)', endsParent: true,
|
||
|
keywords: RUBY_KEYWORDS
|
||
|
};
|
||
|
|
||
|
var 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
|
||
|
}]
|
||
|
}
|
||
|
].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*(\\(|;|$)")),
|
||
|
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;
|
||
|
|
||
|
// >>
|
||
|
// ?>
|
||
|
var SIMPLE_PROMPT = "[>?]>";
|
||
|
// irb(main):001:0>
|
||
|
var DEFAULT_PROMPT = "[\\w#]+\\(\\w+\\):\\d+:\\d+>";
|
||
|
var RVM_PROMPT = "(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>";
|
||
|
|
||
|
var 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;
|