📄 lexperl.cxx
字号:
// ".." is always an operator if preceded by a SCE_PL_WORD.
// Archaic Perl has quotes inside names
if (isMatch(styler, lengthDoc, styler.GetStartSegment(), "__DATA__")) {
styler.ColourTo(i, SCE_PL_DATASECTION);
state = SCE_PL_DATASECTION;
} else if (isMatch(styler, lengthDoc, styler.GetStartSegment(), "__END__")) {
styler.ColourTo(i, SCE_PL_DATASECTION);
state = SCE_PL_DATASECTION;
} else {
if (classifyWordPerl(styler.GetStartSegment(), i, keywords, styler) == SCE_PL_WORD)
preferRE = true;
state = SCE_PL_DEFAULT;
ch = ' ';
}
}
} else {
if (state == SCE_PL_COMMENTLINE) {
if (isEOLChar(ch)) {
styler.ColourTo(i - 1, state);
state = SCE_PL_DEFAULT;
}
} else if (state == SCE_PL_HERE_DELIM) {
//
// From perldata.pod:
// ------------------
// A line-oriented form of quoting is based on the shell ``here-doc''
// syntax.
// Following a << you specify a string to terminate the quoted material,
// and all lines following the current line down to the terminating
// string are the value of the item.
// The terminating string may be either an identifier (a word),
// or some quoted text.
// If quoted, the type of quotes you use determines the treatment of
// the text, just as in regular quoting.
// An unquoted identifier works like double quotes.
// There must be no space between the << and the identifier.
// (If you put a space it will be treated as a null identifier,
// which is valid, and matches the first empty line.)
// The terminating string must appear by itself (unquoted and with no
// surrounding whitespace) on the terminating line.
//
if (HereDoc.State == 0) { // '<<' encountered
HereDoc.State = 1;
HereDoc.Quote = chNext;
HereDoc.Quoted = false;
HereDoc.DelimiterLength = 0;
HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
if (chNext == '\'' || chNext == '"' || chNext == '`') { // a quoted here-doc delimiter
i++;
ch = chNext;
chNext = chNext2;
HereDoc.Quoted = true;
} else if (chNext == '\\') { // ref?
i++;
ch = chNext;
chNext = chNext2;
} else if (isalnum(chNext) || chNext == '_') { // an unquoted here-doc delimiter
}
else if (isspacechar(chNext)) { // deprecated here-doc delimiter || TODO: left shift operator
}
else { // TODO: ???
}
} else if (HereDoc.State == 1) { // collect the delimiter
if (HereDoc.Quoted) { // a quoted here-doc delimiter
if (ch == HereDoc.Quote) { // closing quote => end of delimiter
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
i++;
ch = chNext;
chNext = chNext2;
} else {
if (ch == '\\' && chNext == HereDoc.Quote) { // escaped quote
i++;
ch = chNext;
chNext = chNext2;
}
HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch;
HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
}
} else { // an unquoted here-doc delimiter
if (isalnum(ch) || ch == '_') {
HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch;
HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
} else {
styler.ColourTo(i - 1, state);
state = SCE_PL_DEFAULT;
}
}
if (HereDoc.DelimiterLength >= static_cast<int>(sizeof(HereDoc.Delimiter)) - 1) {
styler.ColourTo(i - 1, state);
state = SCE_PL_ERROR;
}
}
} else if (HereDoc.State == 2) {
// state == SCE_PL_HERE_Q || state == SCE_PL_HERE_QQ || state == SCE_PL_HERE_QX
if (isEOLChar(chPrev) && isMatch(styler, lengthDoc, i, HereDoc.Delimiter)) {
i += HereDoc.DelimiterLength;
chNext = styler.SafeGetCharAt(i);
if (isEOLChar(chNext)) {
styler.ColourTo(i - 1, state);
state = SCE_PL_DEFAULT;
HereDoc.State = 0;
}
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
}
} else if (state == SCE_PL_POD) {
if (ch == '=' && isEOLChar(chPrev)) {
if (isMatch(styler, lengthDoc, i, "=cut")) {
styler.ColourTo(i - 1 + 4, state);
i += 4;
state = SCE_PL_DEFAULT;
ch = styler.SafeGetCharAt(i);
chNext = styler.SafeGetCharAt(i + 1);
}
}
} else if (state == SCE_PL_SCALAR) {
if (isEndVar(ch)) {
if (i == (styler.GetStartSegment() + 1)) {
// Special variable: $(, $_ etc.
styler.ColourTo(i, state);
} else {
styler.ColourTo(i - 1, state);
}
state = SCE_PL_DEFAULT;
}
} else if (state == SCE_PL_ARRAY) {
if (isEndVar(ch)) {
styler.ColourTo(i - 1, state);
state = SCE_PL_DEFAULT;
}
} else if (state == SCE_PL_HASH) {
if (isEndVar(ch)) {
styler.ColourTo(i - 1, state);
state = SCE_PL_DEFAULT;
}
} else if (state == SCE_PL_SYMBOLTABLE) {
if (isEndVar(ch)) {
styler.ColourTo(i - 1, state);
state = SCE_PL_DEFAULT;
}
} else if (state == SCE_PL_REGEX
|| state == SCE_PL_STRING_QR
) {
if (!Quote.Up && !isspacechar(ch)) {
Quote.Open(ch);
} else if (ch == '\\' && Quote.Up != '\\') {
// SG: Is it save to skip *every* escaped char?
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
} else {
if (ch == Quote.Down /*&& chPrev != '\\'*/) {
Quote.Count--;
if (Quote.Count == 0) {
Quote.Rep--;
if (Quote.Up == Quote.Down) {
Quote.Count++;
}
}
if (!isalpha(chNext)) {
if (Quote.Rep <= 0) {
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
ch = ' ';
}
}
} else if (ch == Quote.Up /*&& chPrev != '\\'*/) {
Quote.Count++;
} else if (!isalpha(chNext)) {
if (Quote.Rep <= 0) {
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
ch = ' ';
}
}
}
} else if (state == SCE_PL_REGSUBST) {
if (!Quote.Up && !isspacechar(ch)) {
Quote.Open(ch);
} else if (ch == '\\' && Quote.Up != '\\') {
// SG: Is it save to skip *every* escaped char?
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
} else {
if (Quote.Count == 0 && Quote.Rep == 1) {
/* We matched something like s(...) or tr{...}
* and are looking for the next matcher characters,
* which could be either bracketed ({...}) or non-bracketed
* (/.../).
*
* Number-signs are problematic. If they occur after
* the close of the first part, treat them like
* a Quote.Up char, even if they actually start comments.
*
* If we find an alnum, we end the regsubst, and punt.
*
* Eric Promislow ericp@activestate.com Aug 9,2000
*/
if (isspacechar(ch)) {
// Keep going
}
else if (isalnum(ch)) {
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
ch = ' ';
} else {
Quote.Open(ch);
}
} else if (ch == Quote.Down /*&& chPrev != '\\'*/) {
Quote.Count--;
if (Quote.Count == 0) {
Quote.Rep--;
}
if (!isalpha(chNext)) {
if (Quote.Rep <= 0) {
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
ch = ' ';
}
}
if (Quote.Up == Quote.Down) {
Quote.Count++;
}
} else if (ch == Quote.Up /*&& chPrev != '\\'*/) {
Quote.Count++;
} else if (!isalpha(chNext)) {
if (Quote.Rep <= 0) {
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
ch = ' ';
}
}
}
} else if (state == SCE_PL_STRING_Q
|| state == SCE_PL_STRING_QQ
|| state == SCE_PL_STRING_QX
|| state == SCE_PL_STRING_QW
|| state == SCE_PL_STRING
|| state == SCE_PL_CHARACTER
|| state == SCE_PL_BACKTICKS
) {
if (!Quote.Down && !isspacechar(ch)) {
Quote.Open(ch);
} else if (ch == '\\' && Quote.Up != '\\') {
i++;
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
} else if (ch == Quote.Down) {
Quote.Count--;
if (Quote.Count == 0) {
Quote.Rep--;
if (Quote.Rep <= 0) {
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
ch = ' ';
}
if (Quote.Up == Quote.Down) {
Quote.Count++;
}
}
} else if (ch == Quote.Up) {
Quote.Count++;
}
}
if (state == SCE_PL_DEFAULT) { // One of the above succeeded
if (ch == '#') {
state = SCE_PL_COMMENTLINE;
} else if (ch == '\"') {
state = SCE_PL_STRING;
Quote.New(1);
Quote.Open(ch);
} else if (ch == '\'') {
state = SCE_PL_CHARACTER;
Quote.New(1);
Quote.Open(ch);
} else if (iswordstart(ch)) {
state = SCE_PL_WORD;
preferRE = false;
} else if (isPerlOperator(ch)) {
if (ch == ')' || ch == ']')
preferRE = false;
else
preferRE = true;
styler.ColourTo(i, SCE_PL_OPERATOR);
}
}
}
if (state == SCE_PL_ERROR) {
break;
}
chPrev = ch;
}
styler.ColourTo(lengthDoc - 1, state);
}
static void FoldPerlDoc(unsigned int startPos, int length, int, WordList *[],
Accessor &styler) {
bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
unsigned int endPos = startPos + length;
int visibleChars = 0;
int lineCurrent = styler.GetLine(startPos);
int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
int levelCurrent = levelPrev;
char chNext = styler[startPos];
int styleNext = styler.StyleAt(startPos);
for (unsigned int i = startPos; i < endPos; i++) {
char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
int style = styleNext;
styleNext = styler.StyleAt(i + 1);
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
if (foldComment && (style == SCE_PL_COMMENTLINE)) {
if ((ch == '/') && (chNext == '/')) {
char chNext2 = styler.SafeGetCharAt(i + 2);
if (chNext2 == '{') {
levelCurrent++;
} else if (chNext2 == '}') {
levelCurrent--;
}
}
}
if (style == SCE_C_OPERATOR) {
if (ch == '{') {
levelCurrent++;
} else if (ch == '}') {
levelCurrent--;
}
}
if (atEOL) {
int lev = levelPrev;
if (visibleChars == 0 && foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG;
if ((levelCurrent > levelPrev) && (visibleChars > 0))
lev |= SC_FOLDLEVELHEADERFLAG;
if (lev != styler.LevelAt(lineCurrent)) {
styler.SetLevel(lineCurrent, lev);
}
lineCurrent++;
levelPrev = levelCurrent;
visibleChars = 0;
}
if (!isspacechar(ch))
visibleChars++;
}
// Fill in the real level of the next line, keeping the current flags as they will be filled in later
int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}
static const char * const perlWordListDesc[] = {
"Keywords",
0
};
LexerModule lmPerl(SCLEX_PERL, ColourisePerlDoc, "perl", FoldPerlDoc, perlWordListDesc);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -