📄 lexperl.cxx.svn-base
字号:
}
} 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.)
// (This is deprecated, -w warns of this syntax)
// The terminating string must appear by itself (unquoted and with no
// surrounding whitespace) on the terminating line.
//
// From Bash info:
// ---------------
// Specifier format is: <<[-]WORD
// Optional '-' is for removal of leading tabs from here-doc.
// Whitespace acceptable after <<[-] operator.
//
if (HereDoc.State == 0) { // '<<' encountered
bool gotspace = false;
unsigned int oldi = i;
if (chNext == ' ' || chNext == '\t') {
// skip whitespace; legal for quoted delimiters
gotspace = true;
do {
i++;
chNext = styler.SafeGetCharAt(i + 1);
} while ((i + 1 < lengthDoc) && (chNext == ' ' || chNext == '\t'));
chNext2 = styler.SafeGetCharAt(i + 2);
}
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 (isspacechar(chNext) || isdigit(chNext) || chNext == '\\'
|| chNext == '=' || chNext == '$' || chNext == '@'
|| ((isalpha(chNext) || chNext == '_') && gotspace)) {
// left shift << or <<= operator cases
// restore position if operator
i = oldi;
styler.ColourTo(i, SCE_PL_OPERATOR);
state = SCE_PL_DEFAULT;
HereDoc.State = 0;
goto restartLexer;
} else {
// an unquoted here-doc delimiter, no special handling
// (cannot be prefixed by spaces/tabs), or
// symbols terminates; deprecated zero-length delimiter
}
} else if (HereDoc.State == 1) { // collect the delimiter
backflag = BACK_NONE;
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;
} 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;
goto restartLexer;
}
}
if (HereDoc.DelimiterLength >= HERE_DELIM_MAX - 1) {
styler.ColourTo(i - 1, state);
state = SCE_PL_ERROR;
goto restartLexer;
}
}
} 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;
chPrev = styler.SafeGetCharAt(i - 1);
ch = styler.SafeGetCharAt(i);
if (isEOLChar(ch)) {
styler.ColourTo(i - 1, state);
state = SCE_PL_DEFAULT;
backflag = BACK_NONE;
HereDoc.State = 0;
goto restartLexer;
}
chNext = styler.SafeGetCharAt(i + 1);
}
} else if (state == SCE_PL_POD
|| state == SCE_PL_POD_VERB) {
if (isEOLChar(chPrev)) {
if (ch == ' ' || ch == '\t') {
styler.ColourTo(i - 1, state);
state = SCE_PL_POD_VERB;
} else {
styler.ColourTo(i - 1, state);
state = SCE_PL_POD;
if (ch == '=') {
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);
goto restartLexer;
}
}
}
}
} else if (state == SCE_PL_SCALAR // variable names
|| state == SCE_PL_ARRAY
|| state == SCE_PL_HASH
|| state == SCE_PL_SYMBOLTABLE) {
if (ch == ':' && chNext == ':') { // skip ::
i++;
ch = chNext;
chNext = chNext2;
}
else if (isEndVar(ch)) {
if (i == (styler.GetStartSegment() + 1)) {
// Special variable: $(, $_ etc.
styler.ColourTo(i, state);
state = SCE_PL_DEFAULT;
} else {
styler.ColourTo(i - 1, state);
state = SCE_PL_DEFAULT;
goto restartLexer;
}
}
} 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 (!isascii(chNext) || !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 (!isascii(ch) || 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 (!isascii(chNext) || !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 (!isascii(chNext) || !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_ERROR) {
break;
}
chPrev = ch;
}
styler.ColourTo(lengthDoc - 1, state);
}
static bool IsCommentLine(int line, Accessor &styler) {
int pos = styler.LineStart(line);
int eol_pos = styler.LineStart(line + 1) - 1;
for (int i = pos; i < eol_pos; i++) {
char ch = styler[i];
int style = styler.StyleAt(i);
if (ch == '#' && style == SCE_PL_COMMENTLINE)
return true;
else if (ch != ' ' && ch != '\t')
return false;
}
return false;
}
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;
// Custom folding of POD and packages
bool foldPOD = styler.GetPropertyInt("fold.perl.pod", 1) != 0;
bool foldPackage = styler.GetPropertyInt("fold.perl.package", 1) != 0;
unsigned int endPos = startPos + length;
int visibleChars = 0;
int lineCurrent = styler.GetLine(startPos);
int levelPrev = SC_FOLDLEVELBASE;
if (lineCurrent > 0)
levelPrev = styler.LevelAt(lineCurrent - 1) >> 16;
int levelCurrent = levelPrev;
char chNext = styler[startPos];
char chPrev = styler.SafeGetCharAt(startPos - 1);
int styleNext = styler.StyleAt(startPos);
// Used at end of line to determine if the line was a package definition
bool isPackageLine = false;
bool isPodHeading = false;
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');
bool atLineStart = isEOLChar(chPrev) || i == 0;
// Comment folding
if (foldComment && atEOL && IsCommentLine(lineCurrent, styler))
{
if (!IsCommentLine(lineCurrent - 1, styler)
&& IsCommentLine(lineCurrent + 1, styler))
levelCurrent++;
else if (IsCommentLine(lineCurrent - 1, styler)
&& !IsCommentLine(lineCurrent+1, styler))
levelCurrent--;
}
if (style == SCE_C_OPERATOR) {
if (ch == '{') {
levelCurrent++;
} else if (ch == '}') {
levelCurrent--;
}
}
// Custom POD folding
if (foldPOD && atLineStart) {
int stylePrevCh = (i) ? styler.StyleAt(i - 1):SCE_PL_DEFAULT;
if (style == SCE_PL_POD) {
if (stylePrevCh != SCE_PL_POD && stylePrevCh != SCE_PL_POD_VERB)
levelCurrent++;
else if (styler.Match(i, "=cut"))
levelCurrent--;
else if (styler.Match(i, "=head"))
isPodHeading = true;
} else if (style == SCE_PL_DATASECTION) {
if (ch == '=' && isalpha(chNext) && levelCurrent == SC_FOLDLEVELBASE)
levelCurrent++;
else if (styler.Match(i, "=cut") && levelCurrent > SC_FOLDLEVELBASE)
levelCurrent--;
else if (styler.Match(i, "=head"))
isPodHeading = true;
// if package used or unclosed brace, level > SC_FOLDLEVELBASE!
// reset needed as level test is vs. SC_FOLDLEVELBASE
else if (styler.Match(i, "__END__"))
levelCurrent = SC_FOLDLEVELBASE;
}
}
// Custom package folding
if (foldPackage && atLineStart) {
if (style == SCE_PL_WORD && styler.Match(i, "package")) {
isPackageLine = true;
}
}
if (atEOL) {
int lev = levelPrev;
if (isPodHeading) {
lev = levelPrev - 1;
lev |= SC_FOLDLEVELHEADERFLAG;
isPodHeading = false;
}
// Check if line was a package declaration
// because packages need "special" treatment
if (isPackageLine) {
lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
levelCurrent = SC_FOLDLEVELBASE + 1;
isPackageLine = false;
}
lev |= levelCurrent << 16;
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++;
chPrev = ch;
}
// 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 + -