📄 lexruby.cxx
字号:
} else if (state == SCE_RB_WORD) {
if (ch == '.' || !isSafeWordcharOrHigh(ch)) {
// Words include x? in all contexts,
// and <letters>= after either 'def' or a dot
// Move along until a complete word is on our left
// Default accessor treats '.' as word-chars,
// but we don't for now.
if (ch == '='
&& isSafeWordcharOrHigh(chPrev)
&& (chNext == '('
|| strchr(" \t\n\r", chNext) != NULL)
&& (!strcmp(prevWord, "def")
|| followsDot(styler.GetStartSegment(), styler))) {
// <name>= is a name only when being def'd -- Get it the next time
// This means that <name>=<name> is always lexed as
// <name>, (op, =), <name>
} else if ((ch == '?' || ch == '!')
&& isSafeWordcharOrHigh(chPrev)
&& !isSafeWordcharOrHigh(chNext)) {
// <name>? is a name -- Get it the next time
// But <name>?<name> is always lexed as
// <name>, (op, ?), <name>
// Same with <name>! to indicate a method that
// modifies its target
} else if (isEOLChar(ch)
&& isMatch(styler, lengthDoc, i - 7, "__END__")) {
styler.ColourTo(i, SCE_RB_DATASECTION);
state = SCE_RB_DATASECTION;
// No need to handle this state -- we'll just move to the end
preferRE = false;
} else {
int wordStartPos = styler.GetStartSegment();
int word_style = ClassifyWordRb(wordStartPos, i - 1, keywords, styler, prevWord);
switch (word_style) {
case SCE_RB_WORD:
preferRE = RE_CanFollowKeyword(prevWord);
break;
case SCE_RB_WORD_DEMOTED:
preferRE = true;
break;
case SCE_RB_IDENTIFIER:
if (isMatch(styler, lengthDoc, wordStartPos, "print")) {
preferRE = true;
} else if (isEOLChar(ch)) {
preferRE = true;
} else {
preferRE = false;
}
break;
default:
preferRE = false;
}
if (ch == '.') {
// We might be redefining an operator-method
preferRE = false;
}
// And if it's the first
redo_char(i, ch, chNext, chNext2, state); // pass by ref
}
}
} else if (state == SCE_RB_NUMBER) {
if (!is_real_number) {
if (ch != '\\') {
styler.ColourTo(i, state);
state = SCE_RB_DEFAULT;
preferRE = false;
} else if (strchr("\\ntrfvaebs", chNext)) {
// Terminal escape sequence -- handle it next time
// Nothing more to do this time through the loop
} else if (chNext == 'C' || chNext == 'M') {
if (chNext2 != '-') {
// \C or \M ends the sequence -- handle it next time
} else {
// Move from abc?\C-x
// ^
// to
// ^
i += 2;
ch = chNext2;
chNext = styler.SafeGetCharAt(i + 1);
}
} else if (chNext == 'c') {
// Stay here, \c is a combining sequence
advance_char(i, ch, chNext, chNext2); // pass by ref
} else {
// ?\x, including ?\\ is final.
styler.ColourTo(i + 1, state);
state = SCE_RB_DEFAULT;
preferRE = false;
advance_char(i, ch, chNext, chNext2);
}
} else if (isSafeAlnumOrHigh(ch) || ch == '_') {
// Keep going
} else if (ch == '.' && ++numDots == 1) {
// Keep going
} else {
styler.ColourTo(i - 1, state);
redo_char(i, ch, chNext, chNext2, state); // pass by ref
preferRE = false;
}
} else if (state == SCE_RB_COMMENTLINE) {
if (isEOLChar(ch)) {
styler.ColourTo(i - 1, state);
state = SCE_RB_DEFAULT;
// Use whatever setting we had going into the comment
}
} else if (state == SCE_RB_HERE_DELIM) {
// See the comment for SCE_RB_HERE_DELIM in LexPerl.cxx
// Slightly different: if we find an immediate '-',
// the target can appear indented.
if (HereDoc.State == 0) { // '<<' encountered
HereDoc.State = 1;
HereDoc.DelimiterLength = 0;
if (ch == '-') {
HereDoc.CanBeIndented = true;
advance_char(i, ch, chNext, chNext2); // pass by ref
} else {
HereDoc.CanBeIndented = false;
}
if (isEOLChar(ch)) {
// Bail out of doing a here doc if there's no target
state = SCE_RB_DEFAULT;
preferRE = false;
} else {
HereDoc.Quote = ch;
if (ch == '\'' || ch == '"' || ch == '`') {
HereDoc.Quoted = true;
HereDoc.Delimiter[0] = '\0';
} else {
HereDoc.Quoted = false;
HereDoc.Delimiter[0] = ch;
HereDoc.Delimiter[1] = '\0';
HereDoc.DelimiterLength = 1;
}
}
} else if (HereDoc.State == 1) { // collect the delimiter
if (isEOLChar(ch)) {
// End the quote now, and go back for more
styler.ColourTo(i - 1, state);
state = SCE_RB_DEFAULT;
i--;
chNext = ch;
chNext2 = chNext;
preferRE = false;
} else if (HereDoc.Quoted) {
if (ch == HereDoc.Quote) { // closing quote => end of delimiter
styler.ColourTo(i, state);
state = SCE_RB_DEFAULT;
preferRE = false;
} else {
if (ch == '\\' && !isEOLChar(chNext)) {
advance_char(i, ch, chNext, chNext2);
}
HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch;
HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
}
} else { // an unquoted here-doc delimiter
if (isSafeAlnumOrHigh(ch) || ch == '_') {
HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch;
HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
} else {
styler.ColourTo(i - 1, state);
redo_char(i, ch, chNext, chNext2, state);
preferRE = false;
}
}
if (HereDoc.DelimiterLength >= static_cast<int>(sizeof(HereDoc.Delimiter)) - 1) {
styler.ColourTo(i - 1, state);
state = SCE_RB_ERROR;
preferRE = false;
}
}
} else if (state == SCE_RB_HERE_Q) {
// Not needed: HereDoc.State == 2
// Indentable here docs: look backwards
// Non-indentable: look forwards, like in Perl
//
// Why: so we can quickly resolve things like <<-" abc"
if (!HereDoc.CanBeIndented) {
if (isEOLChar(chPrev)
&& isMatch(styler, lengthDoc, i, HereDoc.Delimiter)) {
styler.ColourTo(i - 1, state);
i += HereDoc.DelimiterLength - 1;
chNext = styler.SafeGetCharAt(i + 1);
if (isEOLChar(chNext)) {
styler.ColourTo(i, SCE_RB_HERE_DELIM);
state = SCE_RB_DEFAULT;
HereDoc.State = 0;
preferRE = false;
}
// Otherwise we skipped through the here doc faster.
}
} else if (isEOLChar(chNext)
&& lookingAtHereDocDelim(styler,
i - HereDoc.DelimiterLength + 1,
lengthDoc,
HereDoc.Delimiter)) {
styler.ColourTo(i - 1 - HereDoc.DelimiterLength, state);
styler.ColourTo(i, SCE_RB_HERE_DELIM);
state = SCE_RB_DEFAULT;
preferRE = false;
HereDoc.State = 0;
}
} else if (state == SCE_RB_CLASS_VAR
|| state == SCE_RB_INSTANCE_VAR
|| state == SCE_RB_SYMBOL) {
if (!isSafeWordcharOrHigh(ch)) {
styler.ColourTo(i - 1, state);
redo_char(i, ch, chNext, chNext2, state); // pass by ref
preferRE = false;
}
} else if (state == SCE_RB_GLOBAL) {
if (!isSafeWordcharOrHigh(ch)) {
// handle special globals here as well
if (chPrev == '$') {
if (ch == '-') {
// Include the next char, like $-a
advance_char(i, ch, chNext, chNext2);
}
styler.ColourTo(i, state);
state = SCE_RB_DEFAULT;
} else {
styler.ColourTo(i - 1, state);
redo_char(i, ch, chNext, chNext2, state); // pass by ref
}
preferRE = false;
}
} else if (state == SCE_RB_POD) {
// PODs end with ^=end\s, -- any whitespace can follow =end
if (strchr(" \t\n\r", ch) != NULL
&& i > 5
&& isEOLChar(styler[i - 5])
&& isMatch(styler, lengthDoc, i - 4, "=end")) {
styler.ColourTo(i - 1, state);
state = SCE_RB_DEFAULT;
preferRE = false;
}
} else if (state == SCE_RB_REGEX || state == SCE_RB_STRING_QR) {
if (ch == '\\' && Quote.Up != '\\') {
// Skip one
advance_char(i, ch, chNext, chNext2);
} else if (ch == Quote.Down) {
Quote.Count--;
if (Quote.Count == 0) {
// Include the options
while (isSafeAlpha(chNext)) {
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
}
styler.ColourTo(i, state);
state = SCE_RB_DEFAULT;
preferRE = false;
}
} else if (ch == Quote.Up) {
// Only if close quoter != open quoter
Quote.Count++;
} else if (ch == '#' ) {
if (chNext == '{'
&& inner_string_count < INNER_STRINGS_MAX_COUNT) {
// process #{ ... }
styler.ColourTo(i - 1, state);
styler.ColourTo(i + 1, SCE_RB_OPERATOR);
enterInnerExpression(inner_string_types,
inner_expn_brace_counts,
inner_quotes,
inner_string_count,
state,
brace_counts,
Quote);
preferRE = true;
// Skip one
advance_char(i, ch, chNext, chNext2);
} else {
//todo: distinguish comments from pound chars
// for now, handle as comment
styler.ColourTo(i - 1, state);
bool inEscape = false;
while (++i < lengthDoc) {
ch = styler.SafeGetCharAt(i);
if (ch == '\\') {
inEscape = true;
} else if (isEOLChar(ch)) {
// Comment inside a regex
styler.ColourTo(i - 1, SCE_RB_COMMENTLINE);
break;
} else if (inEscape) {
inEscape = false; // don't look at char
} else if (ch == Quote.Down) {
// Have the regular handler deal with this
// to get trailing modifiers.
i--;
ch = styler[i];
break;
}
}
chNext = styler.SafeGetCharAt(i + 1);
chNext2 = styler.SafeGetCharAt(i + 2);
}
}
// Quotes of all kinds...
} else if (state == SCE_RB_STRING_Q || state == SCE_RB_STRING_QQ ||
state == SCE_RB_STRING_QX || state == SCE_RB_STRING_QW ||
state == SCE_RB_STRING || state == SCE_RB_CHARACTER ||
state == SCE_RB_BACKTICKS) {
if (!Quote.Down && !isspacechar(ch)) {
Quote.Open(ch);
} else if (ch == '\\' && Quote.Up != '\\') {
//Riddle me this: Is it safe to skip *every* escaped char?
advance_char(i, ch, chNext, chNext2);
} else if (ch == Quote.Down) {
Quote.Count--;
if (Quote.Count == 0) {
styler.ColourTo(i, state);
state = SCE_RB_DEFAULT;
preferRE = false;
}
} else if (ch == Quote.Up) {
Quote.Count++;
} else if (ch == '#' && chNext == '{'
&& inner_string_count < INNER_STRINGS_MAX_COUNT
&& state != SCE_RB_CHARACTER
&& state != SCE_RB_STRING_Q) {
// process #{ ... }
styler.ColourTo(i - 1, state);
styler.ColourTo(i + 1, SCE_RB_OPERATOR);
enterInnerExpression(inner_string_types,
inner_expn_brace_counts,
inner_quotes,
inner_string_count,
state,
brace_counts,
Quote);
preferRE = true;
// Skip one
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -