mirror of
https://github.com/rizonesoft/Notepad3.git
synced 2026-06-14 21:09:05 +08:00
Merge pull request #5683 from RaiKoHoff/Dev_Master
upd: Lexilla Lib v5.4.8 and Scintilla v5.6.1
This commit is contained in:
commit
09a71483fa
@ -102,7 +102,6 @@ knownConditionTrueFalse:lexilla/lexers/LexHex.cxx
|
||||
constVariable:lexilla/lexers/LexHollywood.cxx
|
||||
variableScope:lexilla/lexers/LexInno.cxx
|
||||
constVariableReference:lexilla/lexers/LexInno.cxx
|
||||
constParameterReference:lexilla/lexers/LexJSON.cxx
|
||||
constParameterPointer:lexilla/lexers/LexJulia.cxx
|
||||
constParameterReference:lexilla/lexers/LexJulia.cxx
|
||||
knownConditionTrueFalse:lexilla/lexers/LexJulia.cxx
|
||||
@ -113,7 +112,6 @@ constParameterReference:lexilla/lexers/LexLaTeX.cxx
|
||||
constParameterReference:lexilla/lexers/LexLisp.cxx
|
||||
constParameterPointer:lexilla/lexers/LexMagik.cxx
|
||||
constParameterReference:lexilla/lexers/LexMagik.cxx
|
||||
constParameterReference:lexilla/lexers/LexMarkdown.cxx
|
||||
constParameterPointer:lexilla/lexers/LexMatlab.cxx
|
||||
constParameterReference:lexilla/lexers/LexMatlab.cxx
|
||||
unreadVariable:lexilla/lexers/LexMatlab.cxx
|
||||
@ -240,7 +238,6 @@ constVariableReference:lexilla/lexers/LexMSSQL.cxx
|
||||
constVariableReference:lexilla/lexers/LexNsis.cxx
|
||||
constVariableReference:lexilla/lexers/LexOpal.cxx
|
||||
constVariableReference:lexilla/lexers/LexPOV.cxx
|
||||
constVariableReference:lexilla/lexers/LexPascal.cxx
|
||||
constVariableReference:lexilla/lexers/LexPB.cxx
|
||||
constVariableReference:lexilla/lexers/LexPowerPro.cxx
|
||||
constVariableReference:lexilla/lexers/LexPS.cxx
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<meta name="keywords" content="Scintilla, SciTE, Editing Component, Text Editor" />
|
||||
<meta name="Description"
|
||||
content="www.scintilla.org is the home of the Scintilla editing component and SciTE text editor application." />
|
||||
<meta name="Date.Modified" content="20260225" />
|
||||
<meta name="Date.Modified" content="20260326" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<style type="text/css">
|
||||
.logo {
|
||||
@ -62,8 +62,8 @@
|
||||
<font color="#FFCC99" size="4"> A library of language lexers for use with Scintilla</font>
|
||||
</td>
|
||||
<td width="40%" align="right">
|
||||
<font color="#FFCC99" size="3">Release version 5.4.7<br />
|
||||
Site last modified February 25 2026</font>
|
||||
<font color="#FFCC99" size="3">Release version 5.4.8<br />
|
||||
Site last modified March 26 2026</font>
|
||||
</td>
|
||||
<td width="20%">
|
||||
|
||||
@ -78,11 +78,11 @@
|
||||
</tr>
|
||||
</table>
|
||||
<ul id="versionlist">
|
||||
<li>Version 5.4.8 improves Batch, Forth, JavaScript, and JSON.</li>
|
||||
<li>Version 5.4.7 adds EscapeSequence lexer escseq. Improves Errorlist, Makefile, Perl, and Progress.</li>
|
||||
<li>Version 5.4.6 adds SINEX lexer. Improves Errorlist, Progress, and Python.</li>
|
||||
<li>Version 5.4.5 improves Dart, Makefile, Nix, TOML, and Zig.</li>
|
||||
<li>Version 5.4.4 fixes a problem when building for ARM64 on Windows.</li>
|
||||
<li>Version 5.4.3 improves C++, Modula 3, Pascal, Python, and Ruby.</li>
|
||||
</ul>
|
||||
<ul id="menu">
|
||||
<li id="remote1"><a href="https://www.scintilla.org/SciTEImage.html">Screenshot</a></li>
|
||||
|
||||
@ -26,9 +26,9 @@
|
||||
<table bgcolor="#CCCCCC" width="100%" cellspacing="0" cellpadding="8" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<font size="4"> <a href="https://www.scintilla.org/lexilla547.zip">
|
||||
<font size="4"> <a href="https://www.scintilla.org/lexilla548.zip">
|
||||
Windows</a>
|
||||
<a href="https://www.scintilla.org/lexilla547.tgz">
|
||||
<a href="https://www.scintilla.org/lexilla548.tgz">
|
||||
GTK/Linux</a>
|
||||
</font>
|
||||
</td>
|
||||
@ -42,7 +42,7 @@
|
||||
containing very few restrictions.
|
||||
</p>
|
||||
<h3>
|
||||
Release 5.4.7
|
||||
Release 5.4.8
|
||||
</h3>
|
||||
<h4>
|
||||
Source Code
|
||||
@ -50,8 +50,8 @@
|
||||
The source code package contains all of the source code for Lexilla but no binary
|
||||
executable code and is available in
|
||||
<ul>
|
||||
<li><a href="https://www.scintilla.org/lexilla547.zip">zip format</a> (1.4M) commonly used on Windows</li>
|
||||
<li><a href="https://www.scintilla.org/lexilla547.tgz">tgz format</a> (1.0M) commonly used on Linux and compatible operating systems</li>
|
||||
<li><a href="https://www.scintilla.org/lexilla548.zip">zip format</a> (1.4M) commonly used on Windows</li>
|
||||
<li><a href="https://www.scintilla.org/lexilla548.tgz">tgz format</a> (1.0M) commonly used on Linux and compatible operating systems</li>
|
||||
</ul>
|
||||
Instructions for building on both Windows and Linux are included in the readme file.
|
||||
<h4>
|
||||
|
||||
@ -597,6 +597,38 @@
|
||||
</tr>
|
||||
</table>
|
||||
<h2 id="Releases">Releases</h2>
|
||||
<h3>
|
||||
<a href="https://www.scintilla.org/lexilla548.zip">Release 5.4.8</a>
|
||||
</h3>
|
||||
<ul>
|
||||
<li>
|
||||
Released 26 March 2026.
|
||||
</li>
|
||||
<li>
|
||||
Batch: Remove line length limitation and change to an object lexer.
|
||||
<a href="https://github.com/ScintillaOrg/lexilla/issues/228">Issue #228</a>.
|
||||
</li>
|
||||
<li>
|
||||
Forth: Treat \r\n line ends the same as \n. This makes testing easier.
|
||||
<a href="https://github.com/ScintillaOrg/lexilla/issues/349">Issue #349</a>.
|
||||
</li>
|
||||
<li>
|
||||
Forth: Allow more Forth words to be symbols or begin with a symbol.
|
||||
Require whitespace around line comment tokens,
|
||||
similar to the left-hand parenthesis of stream comments.
|
||||
<a href="https://github.com/ScintillaOrg/lexilla/issues/351">Issue #351</a>.
|
||||
</li>
|
||||
<li>
|
||||
JavaScript: in cpp lexer, add lexer.cpp.enable.preprocessor and lexer.cpp.allow.hashes properties.
|
||||
This allows disabling preprocessor recognition (as JavaScript doesn't have a preprocessor) and
|
||||
recognizing private elements that start with a #.
|
||||
<a href="https://github.com/ScintillaOrg/lexilla/issues/48">Issue #48</a>.
|
||||
</li>
|
||||
<li>
|
||||
JSON: Fix escaped quote in SCE_JSON_URI.
|
||||
<a href="https://github.com/ScintillaOrg/lexilla/issues/72">Issue #72</a>.
|
||||
</li>
|
||||
</ul>
|
||||
<h3>
|
||||
<a href="https://www.scintilla.org/lexilla547.zip">Release 5.4.7</a>
|
||||
</h3>
|
||||
|
||||
@ -492,6 +492,7 @@ public:
|
||||
bashStruct.Set("if elif fi while until else then do done esac eval");
|
||||
bashStruct_in.Set("for case select");
|
||||
testOperator.Set("eq ge gt le lt ne ef nt ot");
|
||||
SetOptionSet(&osBash);
|
||||
}
|
||||
void SCI_METHOD Release() override {
|
||||
delete this;
|
||||
@ -499,30 +500,11 @@ public:
|
||||
int SCI_METHOD Version() const override {
|
||||
return lvRelease5;
|
||||
}
|
||||
const char * SCI_METHOD PropertyNames() override {
|
||||
return osBash.PropertyNames();
|
||||
}
|
||||
int SCI_METHOD PropertyType(const char* name) override {
|
||||
return osBash.PropertyType(name);
|
||||
}
|
||||
const char * SCI_METHOD DescribeProperty(const char *name) override {
|
||||
return osBash.DescribeProperty(name);
|
||||
}
|
||||
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
|
||||
const char * SCI_METHOD PropertyGet(const char* key) override {
|
||||
return osBash.PropertyGet(key);
|
||||
}
|
||||
const char * SCI_METHOD DescribeWordListSets() override {
|
||||
return osBash.DescribeWordListSets();
|
||||
}
|
||||
Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override;
|
||||
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override;
|
||||
void SCI_METHOD Fold(Sci_PositionU startPos_, Sci_Position length, int initStyle, IDocument *pAccess) override;
|
||||
|
||||
void * SCI_METHOD PrivateCall(int, void *) override {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) override {
|
||||
return subStyles.Allocate(styleBase, numberStyles);
|
||||
}
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <map>
|
||||
#include <initializer_list>
|
||||
|
||||
#include "ILexer.h"
|
||||
@ -27,39 +28,113 @@
|
||||
#include "StyleContext.h"
|
||||
#include "CharacterSet.h"
|
||||
#include "LexerModule.h"
|
||||
#include "OptionSet.h"
|
||||
#include "DefaultLexer.h"
|
||||
|
||||
using namespace Lexilla;
|
||||
|
||||
namespace {
|
||||
|
||||
const char *const batchWordListDesc[] = {
|
||||
"Internal Commands",
|
||||
"External Commands",
|
||||
nullptr
|
||||
};
|
||||
|
||||
const LexicalClass lexicalClasses[] = {
|
||||
// Lexer batch SCLEX_BATCH SCE_BAT_
|
||||
0, "SCE_BAT_DEFAULT", "default", "White space",
|
||||
1, "SCE_BAT_COMMENT", "comment", "Line comment",
|
||||
2, "SCE_BAT_WORD", "keyword", "Keyword",
|
||||
3, "SCE_BAT_LABEL", "label", "Label",
|
||||
4, "SCE_BAT_HIDE", "preprocessor", "Hide line @",
|
||||
5, "SCE_BAT_COMMAND", "identifier", "Command",
|
||||
6, "SCE_BAT_IDENTIFIER", "identifier", "Identifier",
|
||||
7, "SCE_BAT_OPERATOR", "operator", "Operator",
|
||||
8, "SCE_BAT_AFTER_LABEL", "comment","After label",
|
||||
};
|
||||
|
||||
class LexerBatch : public DefaultLexer {
|
||||
WordList keywords;
|
||||
WordList keywords2;
|
||||
std::string wordLists;
|
||||
public:
|
||||
explicit LexerBatch() :
|
||||
DefaultLexer("batch", SCLEX_BATCH, lexicalClasses, std::size(lexicalClasses)) {
|
||||
wordLists = JoinWordListDescriptions(batchWordListDesc);
|
||||
}
|
||||
LexerBatch(const LexerBatch &) = delete;
|
||||
LexerBatch(LexerBatch &&) = delete;
|
||||
LexerBatch &operator=(const LexerBatch &) = delete;
|
||||
LexerBatch &operator=(LexerBatch &&) = delete;
|
||||
~LexerBatch() override = default;
|
||||
|
||||
const char *SCI_METHOD DescribeWordListSets() override {
|
||||
return wordLists.c_str();
|
||||
}
|
||||
Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override;
|
||||
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, Scintilla::IDocument *pAccess) override;
|
||||
|
||||
static ILexer5 *LexerFactoryBatch() {
|
||||
return new LexerBatch();
|
||||
}
|
||||
};
|
||||
|
||||
constexpr bool Is0To9(char ch) noexcept {
|
||||
return (ch >= '0') && (ch <= '9');
|
||||
}
|
||||
|
||||
bool IsAlphabetic(int ch) noexcept {
|
||||
return IsASCII(ch) && isalpha(ch);
|
||||
constexpr bool IsAlphabetic(int ch) noexcept {
|
||||
return IsUpperOrLowerCase(ch);
|
||||
}
|
||||
|
||||
inline bool AtEOL(Accessor &styler, Sci_PositionU i) {
|
||||
bool AtEOL(LexAccessor &styler, Sci_PositionU i) {
|
||||
return (styler[i] == '\n') ||
|
||||
((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
|
||||
}
|
||||
|
||||
// Tests for BATCH Operators
|
||||
constexpr bool IsBOperator(char ch) noexcept {
|
||||
return (ch == '=') || (ch == '+') || (ch == '>') || (ch == '<') ||
|
||||
(ch == '|') || (ch == '?') || (ch == '*')||
|
||||
(ch == '&') || (ch == '(') || (ch == ')');
|
||||
return AnyOf(ch, '=', '+', '>', '<', '|', '?', '*', '&', '(', ')');
|
||||
}
|
||||
|
||||
// Tests for BATCH Separators
|
||||
constexpr bool IsBSeparator(char ch) noexcept {
|
||||
return (ch == '\\') || (ch == '.') || (ch == ';') ||
|
||||
(ch == '\"') || (ch == '\'') || (ch == '/');
|
||||
return AnyOf(ch, '\\', '.', ';', '\"', '\'', '/');
|
||||
}
|
||||
|
||||
// Both operators and separators -- words often ended with these characters.
|
||||
constexpr bool IsBPunctuation(char ch) noexcept {
|
||||
return IsBOperator(ch) || IsBSeparator(ch);
|
||||
}
|
||||
|
||||
// These characters end words.
|
||||
constexpr bool IsBEndWord(char ch) noexcept {
|
||||
return IsBPunctuation(ch) || AnyOf(ch, '%', '!');
|
||||
}
|
||||
|
||||
constexpr void SkipSpace(Sci_PositionU &i, std::string_view sv) noexcept {
|
||||
while (i < sv.length() && isspacechar(sv[i])) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr void SkipNonSpace(Sci_PositionU &i, std::string_view sv) noexcept {
|
||||
while (i < sv.length() && !isspacechar(sv[i])) {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr Sci_PositionU WordLength(std::string_view word) {
|
||||
Sci_PositionU i = 0;
|
||||
while ((i < word.length()) && (!IsBEndWord(word[i]))) {
|
||||
i++;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
// Tests for escape character
|
||||
constexpr bool IsEscaped(const char* wordStr, Sci_PositionU pos) noexcept {
|
||||
constexpr bool IsEscaped(std::string_view wordStr, Sci_PositionU pos) noexcept {
|
||||
bool isQoted=false;
|
||||
while (pos>0){
|
||||
pos--;
|
||||
@ -75,7 +150,7 @@ constexpr bool IsQuotedBy(std::string_view svBuffer, char quote) noexcept {
|
||||
bool CurrentStatus = false;
|
||||
size_t pQuote = svBuffer.find(quote);
|
||||
while (pQuote != std::string_view::npos) {
|
||||
if (!IsEscaped(svBuffer.data(), pQuote)) {
|
||||
if (!IsEscaped(svBuffer, pQuote)) {
|
||||
CurrentStatus = !CurrentStatus;
|
||||
}
|
||||
pQuote = svBuffer.find(quote, pQuote + 1);
|
||||
@ -84,17 +159,49 @@ constexpr bool IsQuotedBy(std::string_view svBuffer, char quote) noexcept {
|
||||
}
|
||||
|
||||
// Tests for quote character
|
||||
constexpr bool textQuoted(const char *lineBuffer, Sci_PositionU endPos) noexcept {
|
||||
const std::string_view svBuffer(lineBuffer, endPos);
|
||||
constexpr bool textQuoted(std::string_view lineBuffer, Sci_PositionU endPos) noexcept {
|
||||
const std::string_view svBuffer = lineBuffer.substr(0, endPos);
|
||||
return IsQuotedBy(svBuffer, '\"') || IsQuotedBy(svBuffer, '\'');
|
||||
}
|
||||
|
||||
void ColouriseBatchDoc(
|
||||
Sci_PositionU startPos,
|
||||
Sci_Position length,
|
||||
int /*initStyle*/,
|
||||
WordList *keywordlists[],
|
||||
Accessor &styler) {
|
||||
bool IsContinuation(const std::string &lineBuffer) noexcept {
|
||||
if ((lineBuffer.length() <= 1) || (lineBuffer == "\r\n")) // empty line on Unix and Mac or on Windows
|
||||
return false;
|
||||
Sci_PositionU lineContinuationPos = lineBuffer.length() - 2; // Unix or Mac EOL
|
||||
if ((lineBuffer.length() > 2) && lineBuffer[lineBuffer.length() - 2] == '\r') // Windows EOL
|
||||
lineContinuationPos = lineBuffer.length() - 3;
|
||||
// Reset continueProcessing if line continuation was not found
|
||||
if ((lineBuffer[lineContinuationPos] != '^')
|
||||
|| IsEscaped(lineBuffer, lineContinuationPos)
|
||||
|| textQuoted(lineBuffer, lineContinuationPos))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
Sci_Position SCI_METHOD LexerBatch::WordListSet(int n, const char *wl) {
|
||||
WordList *wordListN = nullptr;
|
||||
switch (n) {
|
||||
case 0:
|
||||
wordListN = &keywords;
|
||||
break;
|
||||
case 1:
|
||||
wordListN = &keywords2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Sci_Position firstModification = -1;
|
||||
if (wordListN) {
|
||||
if (wordListN->Set(wl)) {
|
||||
firstModification = 0;
|
||||
}
|
||||
}
|
||||
return firstModification;
|
||||
}
|
||||
|
||||
void LexerBatch::Lex(Sci_PositionU startPos, Sci_Position length, int, Scintilla::IDocument *pAccess) {
|
||||
LexAccessor styler(pAccess);
|
||||
|
||||
// Always backtracks to the start of a line that is not a continuation
|
||||
// of the previous line
|
||||
if (startPos > 0) {
|
||||
@ -113,24 +220,22 @@ void ColouriseBatchDoc(
|
||||
}
|
||||
}
|
||||
|
||||
char lineBuffer[1024] {};
|
||||
std::string lineBuffer;
|
||||
std::string word;
|
||||
|
||||
styler.StartAt(startPos);
|
||||
styler.StartSegment(startPos);
|
||||
Sci_PositionU linePos = 0;
|
||||
Sci_PositionU startLine = startPos;
|
||||
bool continueProcessing = true; // Used to toggle Regular Keyword Checking
|
||||
bool isNotAssigned=false; // Used to flag Assignment in Set operation
|
||||
|
||||
for (Sci_PositionU i = startPos; i < startPos + length; i++) {
|
||||
lineBuffer[linePos++] = styler[i];
|
||||
if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1) || (i==startPos + length-1)) {
|
||||
// All testing is performed on a lower case version of the line since batch is case-insensitive
|
||||
lineBuffer.push_back(MakeLowerCase(styler[i]));
|
||||
if (AtEOL(styler, i) || (i==startPos + length-1)) {
|
||||
// End of line (or of line buffer) (or End of Last Line) met, colourise it
|
||||
lineBuffer[linePos] = '\0';
|
||||
const Sci_PositionU lengthLine=linePos;
|
||||
const Sci_PositionU lengthLine = lineBuffer.length();
|
||||
const Sci_PositionU endPos=i;
|
||||
const WordList &keywords = *keywordlists[0]; // Internal Commands
|
||||
const WordList &keywords2 = *keywordlists[1]; // External Commands (optional)
|
||||
|
||||
// CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords
|
||||
// Toggling Regular Keyword Checking off improves readability
|
||||
@ -140,9 +245,7 @@ void ColouriseBatchDoc(
|
||||
|
||||
Sci_PositionU offset = 0; // Line Buffer Offset
|
||||
// Skip initial spaces
|
||||
while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
|
||||
offset++;
|
||||
}
|
||||
SkipSpace(offset, lineBuffer);
|
||||
// Colorize Default Text
|
||||
styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
|
||||
// Set External Command / Program Location
|
||||
@ -156,13 +259,13 @@ void ColouriseBatchDoc(
|
||||
} else {
|
||||
// Colorize Real Label
|
||||
// :[\t ]*[^\t &+:<>|]+
|
||||
const char *startLabelName = lineBuffer + offset + 1;
|
||||
const size_t whitespaceLength = strspn(startLabelName, "\t ");
|
||||
const size_t whitespaceEnd = lineBuffer.find_first_not_of("\t ", offset + 1);
|
||||
const size_t whitespaceLength = (whitespaceEnd == std::string::npos) ? 0 : whitespaceEnd;
|
||||
// Set of label-terminating characters determined experimentally
|
||||
const char *endLabel = strpbrk(startLabelName + whitespaceLength, "\t &+:<>|");
|
||||
if (endLabel) {
|
||||
styler.ColourTo(startLine + offset + endLabel - startLabelName, SCE_BAT_LABEL);
|
||||
styler.ColourTo(endPos, SCE_BAT_AFTER_LABEL); // New style
|
||||
const size_t labelEnd = lineBuffer.find_first_of("\t &+:<>|", whitespaceLength);
|
||||
if (labelEnd != std::string::npos) {
|
||||
styler.ColourTo(startLine + labelEnd - 1, SCE_BAT_LABEL);
|
||||
styler.ColourTo(endPos, SCE_BAT_AFTER_LABEL);
|
||||
} else {
|
||||
styler.ColourTo(endPos, SCE_BAT_LABEL);
|
||||
}
|
||||
@ -185,9 +288,7 @@ void ColouriseBatchDoc(
|
||||
offset++;
|
||||
}
|
||||
// Skip next spaces
|
||||
while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
|
||||
offset++;
|
||||
}
|
||||
SkipSpace(offset, lineBuffer);
|
||||
|
||||
// Read remainder of line word-at-a-time or remainder-of-word-at-a-time
|
||||
while (offset < lengthLine && !stopLineProcessing) {
|
||||
@ -195,95 +296,75 @@ void ColouriseBatchDoc(
|
||||
// Colorize Default Text
|
||||
styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
|
||||
}
|
||||
char wordBuffer[81]{}; // Word Buffer - large to catch long paths
|
||||
// Copy word from Line Buffer into Word Buffer and convert to lower case
|
||||
Sci_PositionU wbl = 0; // Word Buffer Length
|
||||
for (; offset < lengthLine && wbl < 80 &&
|
||||
!isspacechar(lineBuffer[offset]); wbl++, offset++) {
|
||||
wordBuffer[wbl] = MakeLowerCase(lineBuffer[offset]);
|
||||
}
|
||||
wordBuffer[wbl] = '\0';
|
||||
const std::string_view wordView(wordBuffer);
|
||||
// Copy word from Line Buffer
|
||||
const Sci_PositionU wordStart = offset;
|
||||
SkipNonSpace(offset, lineBuffer);
|
||||
const Sci_PositionU wbl = offset - wordStart; // Word Buffer Length
|
||||
// Using assign to prevent new allocations
|
||||
word.assign(lineBuffer, wordStart, wbl);
|
||||
const char first = word.front();
|
||||
Sci_PositionU wbo = 0; // Word Buffer Offset - also Special Keyword Buffer Length
|
||||
|
||||
// Check for Comment - return if found
|
||||
if (continueProcessing) {
|
||||
if ((wordView == "rem") || (wordBuffer[0] == ':' && wordBuffer[1] == ':')) {
|
||||
if ((offset == wbl) || !textQuoted(lineBuffer, offset - wbl)) {
|
||||
styler.ColourTo(startLine + offset - wbl - 1, SCE_BAT_DEFAULT);
|
||||
if ((word == "rem") || (word.substr(0,2) == "::")) {
|
||||
if ((offset == wbl) || !textQuoted(lineBuffer, wordStart)) {
|
||||
styler.ColourTo(startLine + wordStart - 1, SCE_BAT_DEFAULT);
|
||||
styler.ColourTo(endPos, SCE_BAT_COMMENT);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Check for Separator
|
||||
if (IsBSeparator(wordBuffer[0])) {
|
||||
if (IsBSeparator(first)) {
|
||||
// Check for External Command / Program
|
||||
if ((cmdLoc == offset - wbl) &&
|
||||
((wordBuffer[0] == ':') ||
|
||||
(wordBuffer[0] == '\\') ||
|
||||
(wordBuffer[0] == '.'))) {
|
||||
int style = SCE_BAT_DEFAULT;
|
||||
if ((cmdLoc == wordStart) &&
|
||||
(AnyOf(first, ':', '\\', '.'))) {
|
||||
// Reset Offset to re-process remainder of word
|
||||
offset -= (wbl - 1);
|
||||
offset = wordStart + 1;
|
||||
// Colorize External Command / Program
|
||||
if (!keywords2) {
|
||||
styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
|
||||
} else if (keywords2.InList(wordBuffer)) {
|
||||
styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
|
||||
} else {
|
||||
styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
|
||||
if ((!keywords2) || (keywords2.InList(word))) {
|
||||
style = SCE_BAT_COMMAND;
|
||||
}
|
||||
// Reset External Command / Program Location
|
||||
cmdLoc = offset;
|
||||
} else {
|
||||
// Reset Offset to re-process remainder of word
|
||||
offset -= (wbl - 1);
|
||||
// Colorize Default Text
|
||||
styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
|
||||
offset = wordStart + 1;
|
||||
}
|
||||
// Colorize Text
|
||||
styler.ColourTo(startLine + offset - 1, style);
|
||||
// Check for Regular Keyword in list
|
||||
} else if ((keywords.InList(wordBuffer)) &&
|
||||
(continueProcessing)) {
|
||||
} else if ((keywords.InList(word)) && (continueProcessing)) {
|
||||
// ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking
|
||||
if (InList(wordView, {"echo", "goto", "prompt"})) {
|
||||
if (InList(word, {"echo", "goto", "prompt"})) {
|
||||
continueProcessing = false;
|
||||
}
|
||||
// SET requires additional processing for the assignment operator
|
||||
if (wordView == "set") {
|
||||
if (word == "set") {
|
||||
continueProcessing = false;
|
||||
isNotAssigned=true;
|
||||
}
|
||||
// Identify External Command / Program Location for ERRORLEVEL, and EXIST
|
||||
if (InList(wordView, {"errorlevel", "exist"})) {
|
||||
if (InList(word, {"errorlevel", "exist"})) {
|
||||
// Reset External Command / Program Location
|
||||
cmdLoc = offset;
|
||||
// Skip next spaces
|
||||
while ((cmdLoc < lengthLine) &&
|
||||
(isspacechar(lineBuffer[cmdLoc]))) {
|
||||
cmdLoc++;
|
||||
}
|
||||
SkipSpace(cmdLoc, lineBuffer);
|
||||
// Skip comparison
|
||||
while ((cmdLoc < lengthLine) &&
|
||||
(!isspacechar(lineBuffer[cmdLoc]))) {
|
||||
cmdLoc++;
|
||||
}
|
||||
SkipNonSpace(cmdLoc, lineBuffer);
|
||||
// Skip next spaces
|
||||
while ((cmdLoc < lengthLine) &&
|
||||
(isspacechar(lineBuffer[cmdLoc]))) {
|
||||
cmdLoc++;
|
||||
}
|
||||
SkipSpace(cmdLoc, lineBuffer);
|
||||
// Identify External Command / Program Location for CALL, DO, LOADHIGH and LH
|
||||
} else if (InList(wordView, {"call", "do", "loadhigh", "lh"})) {
|
||||
} else if (InList(word, {"call", "do", "loadhigh", "lh"})) {
|
||||
// Reset External Command / Program Location
|
||||
cmdLoc = offset;
|
||||
// Skip next spaces
|
||||
while ((cmdLoc < lengthLine) &&
|
||||
(isspacechar(lineBuffer[cmdLoc]))) {
|
||||
cmdLoc++;
|
||||
}
|
||||
SkipSpace(cmdLoc, lineBuffer);
|
||||
// Check if call is followed by a label
|
||||
if ((lineBuffer[cmdLoc] == ':') &&
|
||||
(wordView == "call")) {
|
||||
(word == "call")) {
|
||||
continueProcessing = false;
|
||||
}
|
||||
}
|
||||
@ -291,9 +372,8 @@ void ColouriseBatchDoc(
|
||||
styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD);
|
||||
// No need to Reset Offset
|
||||
// Check for Special Keyword in list, External Command / Program, or Default Text
|
||||
} else if ((wordBuffer[0] != '%') &&
|
||||
(wordBuffer[0] != '!') &&
|
||||
(!IsBOperator(wordBuffer[0])) &&
|
||||
} else if (
|
||||
(!(IsBOperator(first) || AnyOf(first, '%', '!'))) &&
|
||||
(continueProcessing)) {
|
||||
// Check for Special Keyword
|
||||
// Affected Commands are in Length range 2-6
|
||||
@ -302,345 +382,257 @@ void ColouriseBatchDoc(
|
||||
for (Sci_PositionU keywordLength = 2; keywordLength < wbl && keywordLength < 7 && !sKeywordFound; keywordLength++) {
|
||||
// Special Keywords are those that allow certain characters without whitespace after the command
|
||||
// Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path=
|
||||
// Special Keyword Buffer used to determine if the first n characters is a Keyword
|
||||
char sKeywordBuffer[10]{}; // Special Keyword Buffer
|
||||
wbo = 0;
|
||||
// Copy Keyword Length from Word Buffer into Special Keyword Buffer
|
||||
for (; wbo < keywordLength; wbo++) {
|
||||
sKeywordBuffer[wbo] = wordBuffer[wbo];
|
||||
}
|
||||
sKeywordBuffer[wbo] = '\0';
|
||||
// Special Keyword used to determine if the first n characters is a Keyword
|
||||
wbo = keywordLength;
|
||||
const std::string sKeyword = word.substr(0, keywordLength);
|
||||
// Check for Special Keyword in list
|
||||
if ((keywords.InList(sKeywordBuffer)) &&
|
||||
((IsBOperator(wordBuffer[wbo])) ||
|
||||
(IsBSeparator(wordBuffer[wbo])) ||
|
||||
(wordBuffer[wbo] == ':' &&
|
||||
(InList(sKeywordBuffer, {"call", "echo", "goto"}) )))) {
|
||||
if ((keywords.InList(sKeyword)) &&
|
||||
((IsBPunctuation(word[wbo])) ||
|
||||
(word[wbo] == ':' && (InList(sKeyword, {"call", "echo", "goto"}) )))) {
|
||||
sKeywordFound = true;
|
||||
// ECHO requires no further Regular Keyword Checking
|
||||
if (std::string_view(sKeywordBuffer) == "echo") {
|
||||
if (sKeyword== "echo") {
|
||||
continueProcessing = false;
|
||||
}
|
||||
// Colorize Special Keyword as Regular Keyword
|
||||
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_WORD);
|
||||
styler.ColourTo(startLine + wordStart + wbo - 1, SCE_BAT_WORD);
|
||||
// Reset Offset to re-process remainder of word
|
||||
offset -= (wbl - wbo);
|
||||
offset = wordStart + wbo;
|
||||
}
|
||||
}
|
||||
// Check for External Command / Program or Default Text
|
||||
if (!sKeywordFound) {
|
||||
wbo = 0;
|
||||
int style = SCE_BAT_DEFAULT;
|
||||
// Read up to %, !, Operator or Separator
|
||||
const Sci_PositionU lengthWord = WordLength(word);
|
||||
// Check for External Command / Program
|
||||
if (cmdLoc == offset - wbl) {
|
||||
// Read up to %, Operator or Separator
|
||||
while ((wbo < wbl) &&
|
||||
(((wordBuffer[wbo] != '%') &&
|
||||
(wordBuffer[wbo] != '!') &&
|
||||
(!IsBOperator(wordBuffer[wbo])) &&
|
||||
(!IsBSeparator(wordBuffer[wbo]))))) {
|
||||
wbo++;
|
||||
}
|
||||
if (cmdLoc == wordStart) {
|
||||
// Reset External Command / Program Location
|
||||
cmdLoc = offset - (wbl - wbo);
|
||||
// Reset Offset to re-process remainder of word
|
||||
offset -= (wbl - wbo);
|
||||
cmdLoc = wordStart + lengthWord;
|
||||
// CHOICE requires no further Regular Keyword Checking
|
||||
if (wordView == "choice") {
|
||||
if (word == "choice") {
|
||||
continueProcessing = false;
|
||||
}
|
||||
// Check for START (and its switches) - What follows is External Command \ Program
|
||||
if (wordView == "start") {
|
||||
// Reset External Command / Program Location
|
||||
cmdLoc = offset;
|
||||
if (word == "start") {
|
||||
// Skip next spaces
|
||||
while ((cmdLoc < lengthLine) &&
|
||||
(isspacechar(lineBuffer[cmdLoc]))) {
|
||||
cmdLoc++;
|
||||
}
|
||||
SkipSpace(cmdLoc, lineBuffer);
|
||||
// Reset External Command / Program Location if command switch detected
|
||||
if (lineBuffer[cmdLoc] == '/') {
|
||||
// Skip command switch
|
||||
while ((cmdLoc < lengthLine) &&
|
||||
(!isspacechar(lineBuffer[cmdLoc]))) {
|
||||
cmdLoc++;
|
||||
}
|
||||
SkipNonSpace(cmdLoc, lineBuffer);
|
||||
// Skip next spaces
|
||||
while ((cmdLoc < lengthLine) &&
|
||||
(isspacechar(lineBuffer[cmdLoc]))) {
|
||||
cmdLoc++;
|
||||
}
|
||||
SkipSpace(cmdLoc, lineBuffer);
|
||||
}
|
||||
}
|
||||
// Colorize External Command / Program
|
||||
if (!keywords2) {
|
||||
styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
|
||||
} else if (keywords2.InList(wordBuffer)) {
|
||||
styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
|
||||
} else {
|
||||
styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
|
||||
if ((!keywords2) || (keywords2.InList(word))) {
|
||||
style = SCE_BAT_COMMAND;
|
||||
}
|
||||
// No need to Reset Offset
|
||||
// Check for Default Text
|
||||
} else {
|
||||
// Read up to %, Operator or Separator
|
||||
while ((wbo < wbl) &&
|
||||
(((wordBuffer[wbo] != '%') &&
|
||||
(wordBuffer[wbo] != '!') &&
|
||||
(!IsBOperator(wordBuffer[wbo])) &&
|
||||
(!IsBSeparator(wordBuffer[wbo]))))) {
|
||||
wbo++;
|
||||
}
|
||||
// Colorize Default Text
|
||||
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT);
|
||||
// Reset Offset to re-process remainder of word
|
||||
offset -= (wbl - wbo);
|
||||
}
|
||||
styler.ColourTo(startLine + wordStart + lengthWord - 1, style);
|
||||
// Reset Offset to re-process remainder of word
|
||||
offset = wordStart + lengthWord;
|
||||
}
|
||||
// Check for Argument (%n), Environment Variable (%x...%) or Local Variable (%%a)
|
||||
} else if (wordBuffer[0] == '%') {
|
||||
} else if (first == '%') {
|
||||
// Colorize Default Text
|
||||
styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT);
|
||||
styler.ColourTo(startLine + wordStart - 1, SCE_BAT_DEFAULT);
|
||||
wbo++;
|
||||
// Search to end of word for second % (can be a long path)
|
||||
while ((wbo < wbl) &&
|
||||
(wordBuffer[wbo] != '%')) {
|
||||
while ((wbo < wbl) && (word[wbo] != '%')) {
|
||||
wbo++;
|
||||
}
|
||||
// Check for Argument (%n) or (%*)
|
||||
if (((Is0To9(wordBuffer[1])) || (wordBuffer[1] == '*')) &&
|
||||
(wordBuffer[wbo] != '%')) {
|
||||
if (((Is0To9(word[1])) || (word[1] == '*')) &&
|
||||
(word[wbo] != '%')) {
|
||||
// Check for External Command / Program
|
||||
if (cmdLoc == offset - wbl) {
|
||||
cmdLoc = offset - (wbl - 2);
|
||||
if (cmdLoc == wordStart) {
|
||||
cmdLoc = wordStart + 2;
|
||||
}
|
||||
// Colorize Argument
|
||||
styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_IDENTIFIER);
|
||||
styler.ColourTo(startLine + wordStart + 1, SCE_BAT_IDENTIFIER);
|
||||
// Reset Offset to re-process remainder of word
|
||||
offset -= (wbl - 2);
|
||||
offset = wordStart + 2;
|
||||
// Check for Expanded Argument (%~...) / Variable (%%~...)
|
||||
// Expanded Argument: %~[<path-operators>]<single digit>
|
||||
// Expanded Variable: %%~[<path-operators>]<single identifier character>
|
||||
// Path operators are exclusively alphabetic.
|
||||
// Expanded arguments have a single digit at the end.
|
||||
// Expanded variables have a single identifier character as variable name.
|
||||
} else if (((wbl > 1) && (wordBuffer[1] == '~')) ||
|
||||
((wbl > 2) && (wordBuffer[1] == '%') && (wordBuffer[2] == '~'))) {
|
||||
} else if (((wbl > 1) && (word[1] == '~')) ||
|
||||
((wbl > 2) && (word[1] == '%') && (word[2] == '~'))) {
|
||||
// Check for External Command / Program
|
||||
if (cmdLoc == offset - wbl) {
|
||||
cmdLoc = offset - (wbl - wbo);
|
||||
if (cmdLoc == wordStart) {
|
||||
cmdLoc = wordStart + wbo;
|
||||
}
|
||||
const bool isArgument = (wordBuffer[1] == '~');
|
||||
const bool isArgument = (word[1] == '~');
|
||||
if (isArgument) {
|
||||
Sci_PositionU expansionStopOffset = 2;
|
||||
bool isValid = false;
|
||||
for (; expansionStopOffset < wbl; expansionStopOffset++) {
|
||||
if (Is0To9(wordBuffer[expansionStopOffset])) {
|
||||
if (Is0To9(word[expansionStopOffset])) {
|
||||
expansionStopOffset++;
|
||||
isValid = true;
|
||||
wbo = expansionStopOffset;
|
||||
// Colorize Expanded Argument
|
||||
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER);
|
||||
styler.ColourTo(startLine + wordStart + wbo - 1, SCE_BAT_IDENTIFIER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isValid) {
|
||||
// not a valid expanded argument or variable
|
||||
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT);
|
||||
styler.ColourTo(startLine + wordStart + wbo - 1, SCE_BAT_DEFAULT);
|
||||
}
|
||||
// Expanded Variable
|
||||
} else {
|
||||
// start after ~
|
||||
wbo = 3;
|
||||
// Search to end of word for another % (can be a long path)
|
||||
while ((wbo < wbl) &&
|
||||
(wordBuffer[wbo] != '%') &&
|
||||
(!IsBOperator(wordBuffer[wbo])) &&
|
||||
(!IsBSeparator(wordBuffer[wbo]))) {
|
||||
while ((wbo < wbl) && (!(IsBPunctuation(word[wbo]) || (word[wbo] == '%')))) {
|
||||
wbo++;
|
||||
}
|
||||
if (wbo > 3) {
|
||||
// Colorize Expanded Variable
|
||||
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER);
|
||||
styler.ColourTo(startLine + wordStart + wbo - 1, SCE_BAT_IDENTIFIER);
|
||||
} else {
|
||||
// not a valid expanded argument or variable
|
||||
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT);
|
||||
styler.ColourTo(startLine + wordStart + wbo - 1, SCE_BAT_DEFAULT);
|
||||
}
|
||||
}
|
||||
// Reset Offset to re-process remainder of word
|
||||
offset -= (wbl - wbo);
|
||||
offset = wordStart + wbo;
|
||||
// Check for Environment Variable (%x...%)
|
||||
} else if ((wordBuffer[1] != '%') &&
|
||||
(wordBuffer[wbo] == '%')) {
|
||||
} else if ((word[1] != '%') && (word[wbo] == '%')) {
|
||||
wbo++;
|
||||
// Check for External Command / Program
|
||||
if (cmdLoc == offset - wbl) {
|
||||
cmdLoc = offset - (wbl - wbo);
|
||||
if (cmdLoc == wordStart) {
|
||||
cmdLoc = wordStart + wbo;
|
||||
}
|
||||
// Colorize Environment Variable
|
||||
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER);
|
||||
styler.ColourTo(startLine + wordStart + wbo - 1, SCE_BAT_IDENTIFIER);
|
||||
// Reset Offset to re-process remainder of word
|
||||
offset -= (wbl - wbo);
|
||||
offset = wordStart + wbo;
|
||||
// Check for Local Variable (%%a)
|
||||
} else if (
|
||||
(wbl > 2) &&
|
||||
(wordBuffer[1] == '%') &&
|
||||
(wordBuffer[2] != '%') &&
|
||||
(!IsBOperator(wordBuffer[2])) &&
|
||||
(!IsBSeparator(wordBuffer[2]))) {
|
||||
(word[1] == '%') &&
|
||||
(word[2] != '%') &&
|
||||
(!IsBPunctuation(word[2]))) {
|
||||
// Check for External Command / Program
|
||||
if (cmdLoc == offset - wbl) {
|
||||
cmdLoc = offset - (wbl - 3);
|
||||
if (cmdLoc == wordStart) {
|
||||
cmdLoc = wordStart + 3;
|
||||
}
|
||||
// Colorize Local Variable
|
||||
styler.ColourTo(startLine + offset - 1 - (wbl - 3), SCE_BAT_IDENTIFIER);
|
||||
styler.ColourTo(startLine + wordStart + 2, SCE_BAT_IDENTIFIER);
|
||||
// Reset Offset to re-process remainder of word
|
||||
offset -= (wbl - 3);
|
||||
offset = wordStart + 3;
|
||||
// escaped %
|
||||
} else if (
|
||||
(wbl > 1) &&
|
||||
(wordBuffer[1] == '%')) {
|
||||
(word[1] == '%')) {
|
||||
|
||||
// Reset Offset to re-process remainder of word
|
||||
styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_DEFAULT);
|
||||
offset -= (wbl - 2);
|
||||
styler.ColourTo(startLine + wordStart + 1, SCE_BAT_DEFAULT);
|
||||
offset = wordStart + 2;
|
||||
}
|
||||
// Check for Environment Variable (!x...!)
|
||||
} else if (wordBuffer[0] == '!') {
|
||||
} else if (first == '!') {
|
||||
// Colorize Default Text
|
||||
styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT);
|
||||
wbo++;
|
||||
// Search to end of word for second ! (can be a long path)
|
||||
while ((wbo < wbl) &&
|
||||
(wordBuffer[wbo] != '!')) {
|
||||
wbo++;
|
||||
}
|
||||
if (wordBuffer[wbo] == '!') {
|
||||
wbo++;
|
||||
styler.ColourTo(startLine + wordStart - 1, SCE_BAT_DEFAULT);
|
||||
const size_t nextExclamation = word.find('!', 1);
|
||||
if (nextExclamation != std::string::npos) {
|
||||
// Check for External Command / Program
|
||||
if (cmdLoc == offset - wbl) {
|
||||
cmdLoc = offset - (wbl - wbo);
|
||||
if (cmdLoc == wordStart) {
|
||||
cmdLoc = wordStart + nextExclamation + 1;
|
||||
}
|
||||
// Colorize Environment Variable
|
||||
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER);
|
||||
styler.ColourTo(startLine + wordStart + nextExclamation, SCE_BAT_IDENTIFIER);
|
||||
// Reset Offset to re-process remainder of word
|
||||
offset -= (wbl - wbo);
|
||||
offset = wordStart + nextExclamation + 1;
|
||||
}
|
||||
// Check for Operator
|
||||
} else if (IsBOperator(wordBuffer[0])) {
|
||||
} else if (IsBOperator(first)) {
|
||||
// Colorize Default Text
|
||||
styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT);
|
||||
styler.ColourTo(startLine + wordStart - 1, SCE_BAT_DEFAULT);
|
||||
// Check for Comparison Operator
|
||||
if ((wordBuffer[0] == '=') && (wordBuffer[1] == '=')) {
|
||||
if ((first == '=') && (word[1] == '=')) {
|
||||
// Identify External Command / Program Location for IF
|
||||
cmdLoc = offset;
|
||||
// Skip next spaces
|
||||
while ((cmdLoc < lengthLine) &&
|
||||
(isspacechar(lineBuffer[cmdLoc]))) {
|
||||
cmdLoc++;
|
||||
}
|
||||
SkipSpace(cmdLoc, lineBuffer);
|
||||
// Colorize Comparison Operator
|
||||
if (continueProcessing)
|
||||
styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_OPERATOR);
|
||||
styler.ColourTo(startLine + wordStart + 1, SCE_BAT_OPERATOR);
|
||||
else
|
||||
styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_DEFAULT);
|
||||
styler.ColourTo(startLine + wordStart + 1, SCE_BAT_DEFAULT);
|
||||
// Reset Offset to re-process remainder of word
|
||||
offset -= (wbl - 2);
|
||||
offset = wordStart + 2;
|
||||
// Check for Pipe Operator
|
||||
} else if ((wordBuffer[0] == '|') &&
|
||||
!(IsEscaped(lineBuffer,offset - wbl + wbo) || textQuoted(lineBuffer, offset - wbl) )) {
|
||||
} else if ((first == '|') &&
|
||||
!(IsEscaped(lineBuffer, wordStart + wbo) || textQuoted(lineBuffer, wordStart))) {
|
||||
// Reset External Command / Program Location
|
||||
cmdLoc = offset - wbl + 1;
|
||||
cmdLoc = wordStart + 1;
|
||||
// Skip next spaces
|
||||
while ((cmdLoc < lengthLine) &&
|
||||
(isspacechar(lineBuffer[cmdLoc]))) {
|
||||
cmdLoc++;
|
||||
}
|
||||
SkipSpace(cmdLoc, lineBuffer);
|
||||
// Colorize Pipe Operator
|
||||
styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR);
|
||||
styler.ColourTo(startLine + wordStart, SCE_BAT_OPERATOR);
|
||||
// Reset Offset to re-process remainder of word
|
||||
offset -= (wbl - 1);
|
||||
offset = wordStart + 1;
|
||||
continueProcessing = true;
|
||||
// Check for Other Operator
|
||||
} else {
|
||||
// Check for Operators: >, |, &
|
||||
if (((wordBuffer[0] == '>')||
|
||||
(wordBuffer[0] == ')')||
|
||||
(wordBuffer[0] == '(')||
|
||||
(wordBuffer[0] == '&' )) &&
|
||||
!(!continueProcessing && (IsEscaped(lineBuffer,offset - wbl + wbo)
|
||||
|| textQuoted(lineBuffer, offset - wbl) ))){
|
||||
if ((AnyOf(first, '>', ')', '(', '&')) &&
|
||||
!(!continueProcessing && (IsEscaped(lineBuffer, wordStart + wbo)
|
||||
|| textQuoted(lineBuffer, wordStart)))){
|
||||
// Turn Keyword and External Command / Program checking back on
|
||||
continueProcessing = true;
|
||||
isNotAssigned=false;
|
||||
}
|
||||
// Colorize Other Operators
|
||||
// Do not Colorize Parenthesis, quoted text and escaped operators
|
||||
if (((wordBuffer[0] != ')') && (wordBuffer[0] != '(')
|
||||
&& !textQuoted(lineBuffer, offset - wbl) && !IsEscaped(lineBuffer,offset - wbl + wbo))
|
||||
&& !((wordBuffer[0] == '=') && !isNotAssigned ))
|
||||
styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR);
|
||||
if ((!AnyOf(first, ')', '(')
|
||||
&& !textQuoted(lineBuffer, wordStart) && !IsEscaped(lineBuffer, wordStart + wbo))
|
||||
&& !((first == '=') && !isNotAssigned))
|
||||
styler.ColourTo(startLine + wordStart, SCE_BAT_OPERATOR);
|
||||
else
|
||||
styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_DEFAULT);
|
||||
styler.ColourTo(startLine + wordStart, SCE_BAT_DEFAULT);
|
||||
// Reset Offset to re-process remainder of word
|
||||
offset -= (wbl - 1);
|
||||
offset = wordStart + 1;
|
||||
|
||||
if ((wordBuffer[0] == '=') && isNotAssigned ){
|
||||
if ((first == '=') && isNotAssigned){
|
||||
isNotAssigned=false;
|
||||
}
|
||||
}
|
||||
// Check for Default Text
|
||||
} else {
|
||||
// Read up to %, Operator or Separator
|
||||
while ((wbo < wbl) &&
|
||||
((wordBuffer[wbo] != '%') &&
|
||||
(wordBuffer[wbo] != '!') &&
|
||||
(!IsBOperator(wordBuffer[wbo])) &&
|
||||
(!IsBSeparator(wordBuffer[wbo])))) {
|
||||
wbo++;
|
||||
}
|
||||
// Read up to %, !, Operator or Separator
|
||||
const Sci_PositionU lengthWord = WordLength(word);
|
||||
// Colorize Default Text
|
||||
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT);
|
||||
styler.ColourTo(startLine + wordStart + lengthWord - 1, SCE_BAT_DEFAULT);
|
||||
// Reset Offset to re-process remainder of word
|
||||
offset -= (wbl - wbo);
|
||||
offset = wordStart + lengthWord;
|
||||
}
|
||||
// Skip next spaces - nothing happens if Offset was Reset
|
||||
while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
|
||||
offset++;
|
||||
}
|
||||
SkipSpace(offset, lineBuffer);
|
||||
}
|
||||
// Colorize Default Text for remainder of line - currently not lexed
|
||||
styler.ColourTo(endPos, SCE_BAT_DEFAULT);
|
||||
|
||||
// handle line continuation for SET and ECHO commands except the last line
|
||||
if (!continueProcessing && (i<startPos + length-1)) {
|
||||
if (linePos==1 || (linePos==2 && lineBuffer[1]=='\r')) // empty line on Unix and Mac or on Windows
|
||||
continueProcessing=true;
|
||||
else {
|
||||
Sci_PositionU lineContinuationPos;
|
||||
if ((linePos>2) && lineBuffer[linePos-2]=='\r') // Windows EOL
|
||||
lineContinuationPos=linePos-3;
|
||||
else
|
||||
lineContinuationPos=linePos-2; // Unix or Mac EOL
|
||||
// Reset continueProcessing if line continuation was not found
|
||||
if ((lineBuffer[lineContinuationPos]!='^')
|
||||
|| IsEscaped(lineBuffer, lineContinuationPos)
|
||||
|| textQuoted(lineBuffer, lineContinuationPos))
|
||||
continueProcessing=true;
|
||||
}
|
||||
// Reset continueProcessing if line continuation was not found
|
||||
continueProcessing = !IsContinuation(lineBuffer);
|
||||
}
|
||||
|
||||
linePos = 0;
|
||||
lineBuffer.clear();
|
||||
startLine = i + 1;
|
||||
}
|
||||
}
|
||||
styler.Flush();
|
||||
}
|
||||
|
||||
const char *const batchWordListDesc[] = {
|
||||
"Internal Commands",
|
||||
"External Commands",
|
||||
nullptr
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
extern const LexerModule lmBatch(SCLEX_BATCH, ColouriseBatchDoc, "batch", nullptr, batchWordListDesc);
|
||||
extern const LexerModule lmBatch(SCLEX_LUA, LexerBatch::LexerFactoryBatch, "batch", batchWordListDesc);
|
||||
|
||||
@ -388,6 +388,8 @@ constexpr Definition ParseDefine(std::string_view definition, std::string_view e
|
||||
struct OptionsCPP {
|
||||
bool stylingWithinPreprocessor = false;
|
||||
bool identifiersAllowDollars = true;
|
||||
bool identifiersAllowHashes = false;
|
||||
bool enablePreprocessor = true;
|
||||
bool trackPreprocessor = true;
|
||||
bool updatePreprocessor = true;
|
||||
bool verbatimStringsAllowEscapes = false;
|
||||
@ -429,6 +431,12 @@ struct OptionSetCPP : public OptionSet<OptionsCPP> {
|
||||
DefineProperty("lexer.cpp.allow.dollars", &OptionsCPP::identifiersAllowDollars,
|
||||
"Set to 0 to disallow the '$' character in identifiers with the cpp lexer.");
|
||||
|
||||
DefineProperty("lexer.cpp.allow.hashes", &OptionsCPP::identifiersAllowHashes,
|
||||
"Set to 1 to allow the '#' character in identifiers.");
|
||||
|
||||
DefineProperty("lexer.cpp.enable.preprocessor", &OptionsCPP::enablePreprocessor,
|
||||
"Set to 0 to disable recognition of preprocessor directives.");
|
||||
|
||||
DefineProperty("lexer.cpp.track.preprocessor", &OptionsCPP::trackPreprocessor,
|
||||
"Set to 1 to interpret #if/#else/#endif to grey out code that is not active.");
|
||||
|
||||
@ -729,11 +737,15 @@ public:
|
||||
|
||||
Sci_Position SCI_METHOD LexerCPP::PropertySet(const char *key, const char *val) {
|
||||
if (osCPP.PropertySet(&options, key, val)) {
|
||||
if (strcmp(key, "lexer.cpp.allow.dollars") == 0) {
|
||||
const std::string_view keyView(key);
|
||||
if ((keyView == "lexer.cpp.allow.dollars") || (keyView == "lexer.cpp.allow.hashes")) {
|
||||
setWord = CharacterSet(CharacterSet::setAlphaNum, "._", true);
|
||||
if (options.identifiersAllowDollars) {
|
||||
setWord.Add('$');
|
||||
}
|
||||
if (options.identifiersAllowHashes) {
|
||||
setWord.Add('#');
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -803,6 +815,9 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
|
||||
if (options.identifiersAllowDollars) {
|
||||
setWordStart.Add('$');
|
||||
}
|
||||
if (options.identifiersAllowHashes) {
|
||||
setWordStart.Add('#');
|
||||
}
|
||||
|
||||
int chPrevNonWhite = ' ';
|
||||
int visibleChars = 0;
|
||||
@ -1352,7 +1367,7 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
|
||||
sc.SetState(SCE_C_STRING|activitySet);
|
||||
} else if (sc.ch == '\'') {
|
||||
sc.SetState(SCE_C_CHARACTER|activitySet);
|
||||
} else if (sc.ch == '#' && visibleChars == 0) {
|
||||
} else if (sc.ch == '#' && visibleChars == 0 && options.enablePreprocessor) {
|
||||
// Preprocessor commands are alone on their line
|
||||
sc.SetState(SCE_C_PREPROCESSOR|activitySet);
|
||||
// Skip whitespace between # and preprocessor word
|
||||
|
||||
@ -2467,7 +2467,7 @@ void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int
|
||||
} else if (ch == '#' && cssContext == 0) {
|
||||
styler.ColourTo(i - 1, StateToPrint);
|
||||
state = SCE_HCSS_ID;
|
||||
} else if (cssContext == 2 && (IsADigit(ch) || (ch == '-' && IsADigit(chNext)) || (ch == '.' && IsADigit(chNext)) || (ch == '#' && IsADigit(chNext, 16)))) {
|
||||
} else if (cssContext == 2 && (IsADigit(ch) || (ch == '-' && IsADigit(chNext)) || (ch == '.' && IsADigit(chNext)) || (ch == '#' && IsAHeXDigit(chNext)))) {
|
||||
styler.ColourTo(i - 1, StateToPrint);
|
||||
state = SCE_HCSS_NUMBER;
|
||||
} else if (cssContext == 2 && (IsAlphaNumeric(ch) || ch == '-' || ch == '_' || ch == '%')) {
|
||||
|
||||
@ -57,6 +57,9 @@ const LexicalClass lexicalClasses[] = {
|
||||
3, "SCE_MAKE_IDENTIFIER", "identifier", "Identifiers",
|
||||
4, "SCE_MAKE_OPERATOR", "operator", "Operator",
|
||||
5, "SCE_MAKE_TARGET", "identifier", "Identifiers",
|
||||
6, "", "unused", "",
|
||||
7, "", "unused", "",
|
||||
8, "", "unused", "",
|
||||
9, "SCE_MAKE_IDEOL", "error identifier", "Incomplete identifier reference",
|
||||
};
|
||||
|
||||
|
||||
@ -34,11 +34,11 @@
|
||||
*
|
||||
*****************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdio>
|
||||
#include <cstdarg>
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
@ -63,11 +63,9 @@ constexpr bool IsNewline(const int ch) {
|
||||
return (ch == '\n' || ch == '\r' || ch == '\0');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// True if can follow ch down to the end with possibly trailing whitespace
|
||||
// Does not set the state SCE_MARKDOWN_LINE_BEGIN as to allow further processing
|
||||
static bool FollowToLineEnd(const int ch, const int state, const Sci_PositionU endPos, StyleContext &sc) {
|
||||
bool FollowToLineEnd(const int ch, const int state, const Sci_PositionU endPos, StyleContext &sc) {
|
||||
Sci_Position i = 0;
|
||||
while (sc.GetRelative(++i) == ch)
|
||||
;
|
||||
@ -79,12 +77,12 @@ static bool FollowToLineEnd(const int ch, const int state, const Sci_PositionU e
|
||||
sc.Forward(i);
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the state on text section from current to length characters,
|
||||
// then set the rest until the newline to default, except for any characters matching token
|
||||
static void SetStateAndZoom(const int state, const Sci_Position length, const int token, StyleContext &sc) {
|
||||
void SetStateAndZoom(const int state, const Sci_Position length, const int token, StyleContext &sc) {
|
||||
sc.SetState(state);
|
||||
sc.Forward(length);
|
||||
sc.SetState(SCE_MARKDOWN_DEFAULT);
|
||||
@ -105,7 +103,7 @@ static void SetStateAndZoom(const int state, const Sci_Position length, const in
|
||||
}
|
||||
|
||||
// Does the previous line have more than spaces and tabs?
|
||||
static bool HasPrevLineContent(StyleContext &sc) {
|
||||
bool HasPrevLineContent(StyleContext &sc) {
|
||||
Sci_Position i = 0;
|
||||
// Go back to the previous newline
|
||||
while ((--i + (Sci_Position)sc.currentPos) >= 0 && !IsNewline(sc.GetRelative(i)))
|
||||
@ -120,11 +118,11 @@ static bool HasPrevLineContent(StyleContext &sc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool AtTermStart(StyleContext &sc) {
|
||||
bool AtTermStart(const StyleContext &sc) noexcept {
|
||||
return sc.currentPos == 0 || sc.chPrev == 0 || isspacechar(sc.chPrev);
|
||||
}
|
||||
|
||||
static bool IsCompleteStyleRegion(StyleContext &sc, const char *token) {
|
||||
bool IsCompleteStyleRegion(StyleContext &sc, const char *token) {
|
||||
bool found = false;
|
||||
const size_t start = strlen(token);
|
||||
Sci_Position i = static_cast<Sci_Position>(start);
|
||||
@ -140,12 +138,12 @@ static bool IsCompleteStyleRegion(StyleContext &sc, const char *token) {
|
||||
return AtTermStart(sc) && found;
|
||||
}
|
||||
|
||||
static bool IsValidHrule(const Sci_PositionU endPos, StyleContext &sc) {
|
||||
bool IsValidHrule(const Sci_PositionU endPos, StyleContext &sc) {
|
||||
int count = 1;
|
||||
Sci_Position i = 0;
|
||||
for (;;) {
|
||||
++i;
|
||||
int c = sc.GetRelative(i);
|
||||
const int c = sc.GetRelative(i);
|
||||
if (c == sc.ch)
|
||||
++count;
|
||||
// hit a terminating character
|
||||
@ -158,17 +156,15 @@ static bool IsValidHrule(const Sci_PositionU endPos, StyleContext &sc) {
|
||||
sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
sc.SetState(SCE_MARKDOWN_DEFAULT);
|
||||
return false;
|
||||
}
|
||||
sc.SetState(SCE_MARKDOWN_DEFAULT);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ColorizeMarkdownDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
|
||||
void ColorizeMarkdownDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
|
||||
WordList **, Accessor &styler) {
|
||||
Sci_PositionU endPos = startPos + length;
|
||||
const Sci_PositionU endPos = startPos + length;
|
||||
int precharCount = 0;
|
||||
bool isLinkNameDetecting = false;
|
||||
// Don't advance on a new loop iteration and retry at the same position.
|
||||
@ -178,7 +174,7 @@ static void ColorizeMarkdownDoc(Sci_PositionU startPos, Sci_Position length, int
|
||||
|
||||
// property lexer.markdown.header.eolfill
|
||||
// Set to 1 to highlight all ATX header text.
|
||||
bool headerEOLFill = styler.GetPropertyInt("lexer.markdown.header.eolfill", 0) == 1;
|
||||
const bool headerEOLFill = styler.GetPropertyInt("lexer.markdown.header.eolfill", 0) == 1;
|
||||
|
||||
StyleContext sc(startPos, static_cast<Sci_PositionU>(length), initStyle, styler);
|
||||
|
||||
@ -483,4 +479,6 @@ static void ColorizeMarkdownDoc(Sci_PositionU startPos, Sci_Position length, int
|
||||
sc.Complete();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern const LexerModule lmMarkdown(SCLEX_MARKDOWN, ColorizeMarkdownDoc, "markdown");
|
||||
|
||||
@ -110,15 +110,13 @@ contains requires
|
||||
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <cstdlib>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <map>
|
||||
|
||||
#include "ILexer.h"
|
||||
#include "Scintilla.h"
|
||||
@ -130,32 +128,134 @@ contains requires
|
||||
#include "StyleContext.h"
|
||||
#include "CharacterSet.h"
|
||||
#include "LexerModule.h"
|
||||
#include "OptionSet.h"
|
||||
#include "DefaultLexer.h"
|
||||
|
||||
using namespace Lexilla;
|
||||
|
||||
namespace {
|
||||
|
||||
void GetRangeLowered(Sci_PositionU start,
|
||||
Sci_PositionU end,
|
||||
Accessor &styler,
|
||||
// Options used for LexerPascal
|
||||
struct OptionsPascal {
|
||||
bool bSmartHighlighting = true;
|
||||
bool fold = false;
|
||||
bool foldComment = false;
|
||||
bool foldPreprocessor = false;
|
||||
bool foldCompact = true;
|
||||
};
|
||||
|
||||
const char *const pascalWordListDesc[] = {
|
||||
"Keywords",
|
||||
nullptr
|
||||
};
|
||||
|
||||
struct OptionSetPascal : public OptionSet<OptionsPascal> {
|
||||
OptionSetPascal() {
|
||||
DefineProperty("lexer.pascal.smart.highlighting", &OptionsPascal::bSmartHighlighting,
|
||||
"Set to 0 to not completely handle some complex features like 'property'.");
|
||||
|
||||
DefineProperty("fold", &OptionsPascal::fold);
|
||||
|
||||
DefineProperty("fold.comment", &OptionsPascal::foldComment);
|
||||
|
||||
DefineProperty("fold.preprocessor", &OptionsPascal::foldPreprocessor);
|
||||
|
||||
DefineProperty("fold.compact", &OptionsPascal::foldCompact);
|
||||
|
||||
DefineWordListSets(pascalWordListDesc);
|
||||
}
|
||||
};
|
||||
|
||||
const LexicalClass lexicalClasses[] = {
|
||||
// Lexer pascal SCLEX_PASCAL SCE_PAS_
|
||||
0, "SCE_PAS_DEFAULT", "default", "White space",
|
||||
1, "SCE_PAS_IDENTIFIER", "identifier", "Identifier",
|
||||
2, "SCE_PAS_COMMENT", "comment", "Comment: { ... }",
|
||||
3, "SCE_PAS_COMMENT2", "comment", "Comment: (* ... *)",
|
||||
4, "SCE_PAS_COMMENTLINE","comment line", "Line Comment: // ...",
|
||||
5, "SCE_PAS_PREPROCESSOR", "preprocessor", "Preprocessor: {$ ... }",
|
||||
6, "SCE_PAS_PREPROCESSOR2", "preprocessor", "Preprocessor: (*$ ... *)",
|
||||
7, "SCE_PAS_NUMBER", "literal numeric", "Number",
|
||||
8, "SCE_PAS_HEXNUMBER", "literal numeric", "Hex Number",
|
||||
9, "SCE_PAS_WORD", "keyword", "Keyword",
|
||||
10, "SCE_PAS_STRING", "literal string", "Single quoted string",
|
||||
11, "SCE_PAS_STRINGEOL", "error literal string", "End of line where string is not closed",
|
||||
12, "SCE_PAS_CHARACTER","literal string character", "Character",
|
||||
13, "SCE_PAS_OPERATOR","operator", "Operator",
|
||||
14, "SCE_PAS_ASM", "assembler", "Inline Assembler",
|
||||
};
|
||||
|
||||
class LexerPascal : public DefaultLexer {
|
||||
WordList keywords;
|
||||
OptionsPascal options;
|
||||
OptionSetPascal osPascal;
|
||||
public:
|
||||
explicit LexerPascal() :
|
||||
DefaultLexer("pascal", SCLEX_PASCAL, lexicalClasses, std::size(lexicalClasses)) {
|
||||
SetOptionSet(&osPascal);
|
||||
}
|
||||
LexerPascal(const LexerPascal &) = delete;
|
||||
LexerPascal(LexerPascal &&) = delete;
|
||||
LexerPascal &operator=(const LexerPascal &) = delete;
|
||||
LexerPascal &operator=(LexerPascal &&) = delete;
|
||||
~LexerPascal() override = default;
|
||||
|
||||
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
|
||||
Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override;
|
||||
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, Scintilla::IDocument *pAccess) override;
|
||||
void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, Scintilla::IDocument *pAccess) override;
|
||||
|
||||
static ILexer5 *LexerFactoryPascal() {
|
||||
return new LexerPascal();
|
||||
}
|
||||
};
|
||||
|
||||
Sci_Position SCI_METHOD LexerPascal::PropertySet(const char *key, const char *val) {
|
||||
if (osPascal.PropertySet(&options, key, val)) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
Sci_Position SCI_METHOD LexerPascal::WordListSet(int n, const char *wl) {
|
||||
WordList *wordListN = nullptr;
|
||||
switch (n) {
|
||||
case 0:
|
||||
wordListN = &keywords;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
Sci_Position firstModification = -1;
|
||||
if (wordListN) {
|
||||
if (wordListN->Set(wl)) {
|
||||
firstModification = 0;
|
||||
}
|
||||
}
|
||||
return firstModification;
|
||||
}
|
||||
|
||||
void GetRangeLowered(Sci_Position start,
|
||||
Sci_Position end,
|
||||
LexAccessor &styler,
|
||||
char *s,
|
||||
Sci_PositionU len) {
|
||||
Sci_PositionU i = 0;
|
||||
Sci_Position len) {
|
||||
Sci_Position i = 0;
|
||||
while ((i < end - start + 1) && (i < len-1)) {
|
||||
s[i] = static_cast<char>(tolower(styler[start + i]));
|
||||
s[i] = MakeLowerCase(styler[start + i]);
|
||||
i++;
|
||||
}
|
||||
s[i] = '\0';
|
||||
}
|
||||
|
||||
void GetForwardRangeLowered(Sci_PositionU start,
|
||||
CharacterSet &charSet,
|
||||
Accessor &styler,
|
||||
void GetForwardRangeLowered(Sci_Position start,
|
||||
const CharacterSet &charSet,
|
||||
LexAccessor &styler,
|
||||
char *s,
|
||||
Sci_PositionU len) {
|
||||
Sci_PositionU i = 0;
|
||||
Sci_Position len) {
|
||||
Sci_Position i = 0;
|
||||
while ((i < len-1) && charSet.Contains(styler.SafeGetCharAt(start + i))) {
|
||||
s[i] = static_cast<char>(tolower(styler.SafeGetCharAt(start + i)));
|
||||
s[i] = MakeLowerCase(styler.SafeGetCharAt(start + i));
|
||||
i++;
|
||||
}
|
||||
s[i] = '\0';
|
||||
@ -172,9 +272,7 @@ enum {
|
||||
stateFoldMaskAll = 0x0FFF
|
||||
};
|
||||
|
||||
void ClassifyPascalWord(WordList *keywordlists[], StyleContext &sc, int &curLineState, bool bSmartHighlighting) {
|
||||
WordList& keywords = *keywordlists[0];
|
||||
|
||||
void ClassifyPascalWord(const WordList &keywords, StyleContext &sc, int &curLineState, bool bSmartHighlighting) {
|
||||
char s[100];
|
||||
sc.GetCurrentLowered(s, sizeof(s));
|
||||
if (keywords.InList(s)) {
|
||||
@ -217,15 +315,14 @@ void ClassifyPascalWord(WordList *keywordlists[], StyleContext &sc, int &curLine
|
||||
sc.SetState(SCE_PAS_DEFAULT);
|
||||
}
|
||||
|
||||
void ColourisePascalDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[],
|
||||
Accessor &styler) {
|
||||
bool bSmartHighlighting = styler.GetPropertyInt("lexer.pascal.smart.highlighting", 1) != 0;
|
||||
void LexerPascal::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, Scintilla::IDocument *pAccess) {
|
||||
LexAccessor styler(pAccess);
|
||||
|
||||
CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
|
||||
CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true);
|
||||
CharacterSet setNumber(CharacterSet::setDigits, ".-+eE");
|
||||
CharacterSet setHexNumber(CharacterSet::setDigits, "abcdefABCDEF");
|
||||
CharacterSet setOperator(CharacterSet::setNone, "#$&'()*+,-./:;<=>@[]^{}");
|
||||
const CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
|
||||
const CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true);
|
||||
const CharacterSet setNumber(CharacterSet::setDigits, ".-+eE");
|
||||
const CharacterSet setHexNumber(CharacterSet::setDigits, "abcdefABCDEF");
|
||||
const CharacterSet setOperator(CharacterSet::setNone, "#$&'()*+,-./:;<=>@[]^{}");
|
||||
|
||||
int curLineState = 0;
|
||||
|
||||
@ -248,7 +345,7 @@ void ColourisePascalDoc(Sci_PositionU startPos, Sci_Position length, int initSty
|
||||
break;
|
||||
case SCE_PAS_IDENTIFIER:
|
||||
if (!setWord.Contains(sc.ch)) {
|
||||
ClassifyPascalWord(keywordlists, sc, curLineState, bSmartHighlighting);
|
||||
ClassifyPascalWord(keywords, sc, curLineState, options.bSmartHighlighting);
|
||||
}
|
||||
break;
|
||||
case SCE_PAS_HEXNUMBER:
|
||||
@ -294,7 +391,7 @@ void ColourisePascalDoc(Sci_PositionU startPos, Sci_Position length, int initSty
|
||||
}
|
||||
break;
|
||||
case SCE_PAS_OPERATOR:
|
||||
if (bSmartHighlighting && sc.chPrev == ';') {
|
||||
if (options.bSmartHighlighting && sc.chPrev == ';') {
|
||||
curLineState &= ~(stateInProperty | stateInExport);
|
||||
}
|
||||
sc.SetState(SCE_PAS_DEFAULT);
|
||||
@ -341,23 +438,23 @@ void ColourisePascalDoc(Sci_PositionU startPos, Sci_Position length, int initSty
|
||||
}
|
||||
|
||||
if (sc.state == SCE_PAS_IDENTIFIER && setWord.Contains(sc.chPrev)) {
|
||||
ClassifyPascalWord(keywordlists, sc, curLineState, bSmartHighlighting);
|
||||
ClassifyPascalWord(keywords, sc, curLineState, options.bSmartHighlighting);
|
||||
}
|
||||
|
||||
sc.Complete();
|
||||
}
|
||||
|
||||
bool IsStreamCommentStyle(int style) {
|
||||
constexpr bool IsStreamCommentStyle(int style) noexcept {
|
||||
return style == SCE_PAS_COMMENT || style == SCE_PAS_COMMENT2;
|
||||
}
|
||||
|
||||
bool IsCommentLine(Sci_Position line, Accessor &styler) {
|
||||
Sci_Position pos = styler.LineStart(line);
|
||||
Sci_Position eolPos = styler.LineStart(line + 1) - 1;
|
||||
bool IsCommentLine(Sci_Position line, LexAccessor &styler) {
|
||||
const Sci_Position pos = styler.LineStart(line);
|
||||
const Sci_Position eolPos = styler.LineStart(line + 1) - 1;
|
||||
for (Sci_Position i = pos; i < eolPos; i++) {
|
||||
char ch = styler[i];
|
||||
char chNext = styler.SafeGetCharAt(i + 1);
|
||||
int style = styler.StyleAt(i);
|
||||
const char ch = styler[i];
|
||||
const char chNext = styler.SafeGetCharAt(i + 1);
|
||||
const int style = styler.StyleIndexAt(i);
|
||||
if (ch == '/' && chNext == '/' && style == SCE_PAS_COMMENTLINE) {
|
||||
return true;
|
||||
} else if (!IsASpaceOrTab(ch)) {
|
||||
@ -367,18 +464,18 @@ bool IsCommentLine(Sci_Position line, Accessor &styler) {
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int GetFoldInPreprocessorLevelFlag(int lineFoldStateCurrent) {
|
||||
constexpr unsigned int GetFoldInPreprocessorLevelFlag(int lineFoldStateCurrent) noexcept {
|
||||
return lineFoldStateCurrent & stateFoldInPreprocessorLevelMask;
|
||||
}
|
||||
|
||||
void SetFoldInPreprocessorLevelFlag(int &lineFoldStateCurrent, unsigned int nestLevel) {
|
||||
void SetFoldInPreprocessorLevelFlag(int &lineFoldStateCurrent, unsigned int nestLevel) noexcept {
|
||||
lineFoldStateCurrent &= ~stateFoldInPreprocessorLevelMask;
|
||||
lineFoldStateCurrent |= nestLevel & stateFoldInPreprocessorLevelMask;
|
||||
}
|
||||
|
||||
void ClassifyPascalPreprocessorFoldPoint(int &levelCurrent, int &lineFoldStateCurrent,
|
||||
Sci_PositionU startPos, Accessor &styler) {
|
||||
CharacterSet setWord(CharacterSet::setAlpha);
|
||||
Sci_Position startPos, LexAccessor &styler) {
|
||||
const CharacterSet setWord(CharacterSet::setAlpha);
|
||||
|
||||
char s[11]; // Size of the longest possible keyword + one additional character + null
|
||||
GetForwardRangeLowered(startPos, setWord, styler, s, sizeof(s));
|
||||
@ -409,10 +506,10 @@ void ClassifyPascalPreprocessorFoldPoint(int &levelCurrent, int &lineFoldStateCu
|
||||
}
|
||||
}
|
||||
|
||||
Sci_PositionU SkipWhiteSpace(Sci_PositionU currentPos, Sci_PositionU endPos,
|
||||
Accessor &styler, bool includeChars = false) {
|
||||
CharacterSet setWord(CharacterSet::setAlphaNum, "_");
|
||||
Sci_PositionU j = currentPos + 1;
|
||||
Sci_Position SkipWhiteSpace(Sci_Position currentPos, Sci_Position endPos,
|
||||
LexAccessor &styler, bool includeChars = false) {
|
||||
const CharacterSet setWord(CharacterSet::setAlphaNum, "_");
|
||||
Sci_Position j = currentPos + 1;
|
||||
char ch = styler.SafeGetCharAt(j);
|
||||
while ((j < endPos) && (IsASpaceOrTab(ch) || ch == '\r' || ch == '\n' ||
|
||||
IsStreamCommentStyle(styler.StyleAt(j)) || (includeChars && setWord.Contains(ch)))) {
|
||||
@ -423,8 +520,8 @@ Sci_PositionU SkipWhiteSpace(Sci_PositionU currentPos, Sci_PositionU endPos,
|
||||
}
|
||||
|
||||
void ClassifyPascalWordFoldPoint(int &levelCurrent, int &lineFoldStateCurrent,
|
||||
Sci_Position startPos, Sci_PositionU endPos,
|
||||
Sci_PositionU lastStart, Sci_PositionU currentPos, Accessor &styler) {
|
||||
Sci_Position startPos, Sci_Position endPos,
|
||||
Sci_Position lastStart, Sci_Position currentPos, LexAccessor &styler) {
|
||||
char s[100];
|
||||
GetRangeLowered(lastStart, currentPos, styler, s, sizeof(s));
|
||||
|
||||
@ -439,10 +536,10 @@ void ClassifyPascalWordFoldPoint(int &levelCurrent, int &lineFoldStateCurrent,
|
||||
} else if (strcmp(s, "class") == 0 || strcmp(s, "object") == 0) {
|
||||
// "class" & "object" keywords require special handling...
|
||||
bool ignoreKeyword = false;
|
||||
Sci_PositionU j = SkipWhiteSpace(currentPos, endPos, styler);
|
||||
Sci_Position j = SkipWhiteSpace(currentPos, endPos, styler);
|
||||
if (j < endPos) {
|
||||
CharacterSet setWordStart(CharacterSet::setAlpha, "_");
|
||||
CharacterSet setWord(CharacterSet::setAlphaNum, "_");
|
||||
const CharacterSet setWordStart(CharacterSet::setAlpha, "_");
|
||||
const CharacterSet setWord(CharacterSet::setAlphaNum, "_");
|
||||
|
||||
if (styler.SafeGetCharAt(j) == ';') {
|
||||
// Handle forward class declarations ("type TMyClass = class;")
|
||||
@ -491,7 +588,7 @@ void ClassifyPascalWordFoldPoint(int &levelCurrent, int &lineFoldStateCurrent,
|
||||
ignoreKeyword = false;
|
||||
}
|
||||
if (!ignoreKeyword) {
|
||||
Sci_PositionU k = SkipWhiteSpace(currentPos, endPos, styler);
|
||||
const Sci_Position k = SkipWhiteSpace(currentPos, endPos, styler);
|
||||
if (k < endPos && styler.SafeGetCharAt(k) == ';') {
|
||||
// Handle forward interface declarations ("type IMyInterface = interface;")
|
||||
ignoreKeyword = true;
|
||||
@ -503,7 +600,7 @@ void ClassifyPascalWordFoldPoint(int &levelCurrent, int &lineFoldStateCurrent,
|
||||
} else if (strcmp(s, "dispinterface") == 0) {
|
||||
// "dispinterface" keyword requires special handling...
|
||||
bool ignoreKeyword = false;
|
||||
Sci_PositionU j = SkipWhiteSpace(currentPos, endPos, styler);
|
||||
const Sci_Position j = SkipWhiteSpace(currentPos, endPos, styler);
|
||||
if (j < endPos && styler.SafeGetCharAt(j) == ';') {
|
||||
// Handle forward dispinterface declarations ("type IMyInterface = dispinterface;")
|
||||
ignoreKeyword = true;
|
||||
@ -520,33 +617,44 @@ void ClassifyPascalWordFoldPoint(int &levelCurrent, int &lineFoldStateCurrent,
|
||||
}
|
||||
}
|
||||
|
||||
void FoldPascalDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *[],
|
||||
Accessor &styler) {
|
||||
bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
|
||||
bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
|
||||
bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
|
||||
Sci_PositionU endPos = startPos + length;
|
||||
int visibleChars = 0;
|
||||
void LexerPascal::Fold(Sci_PositionU startPos_, Sci_Position length, int initStyle, Scintilla::IDocument *pAccess) {
|
||||
|
||||
if (!options.fold)
|
||||
return;
|
||||
|
||||
LexAccessor styler(pAccess);
|
||||
|
||||
Sci_Position startPos = startPos_;
|
||||
const Sci_Position endPos = startPos + length;
|
||||
Sci_Position lineCurrent = styler.GetLine(startPos);
|
||||
// Backtrack to previous line in case need to fix its fold status
|
||||
if (lineCurrent > 0) {
|
||||
lineCurrent--;
|
||||
startPos = styler.LineStart(lineCurrent);
|
||||
initStyle = (startPos > 0) ? styler.StyleIndexAt(startPos - 1) : 0;
|
||||
}
|
||||
|
||||
int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
|
||||
int levelCurrent = levelPrev;
|
||||
int lineFoldStateCurrent = lineCurrent > 0 ? styler.GetLineState(lineCurrent - 1) & stateFoldMaskAll : 0;
|
||||
char chNext = styler[startPos];
|
||||
int styleNext = styler.StyleAt(startPos);
|
||||
int styleNext = styler.StyleIndexAt(startPos);
|
||||
int style = initStyle;
|
||||
|
||||
int visibleChars = 0;
|
||||
|
||||
Sci_Position lastStart = 0;
|
||||
CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true);
|
||||
const CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true);
|
||||
|
||||
for (Sci_PositionU i = startPos; i < endPos; i++) {
|
||||
char ch = chNext;
|
||||
for (Sci_Position i = startPos; i < endPos; i++) {
|
||||
const char ch = chNext;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
int stylePrev = style;
|
||||
const int stylePrev = style;
|
||||
style = styleNext;
|
||||
styleNext = styler.StyleAt(i + 1);
|
||||
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
|
||||
styleNext = styler.StyleIndexAt(i + 1);
|
||||
const bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
|
||||
|
||||
if (foldComment && IsStreamCommentStyle(style)) {
|
||||
if (options.foldComment && IsStreamCommentStyle(style)) {
|
||||
if (!IsStreamCommentStyle(stylePrev)) {
|
||||
levelCurrent++;
|
||||
} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
|
||||
@ -554,7 +662,7 @@ void FoldPascalDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, W
|
||||
levelCurrent--;
|
||||
}
|
||||
}
|
||||
if (foldComment && atEOL && IsCommentLine(lineCurrent, styler))
|
||||
if (options.foldComment && atEOL && IsCommentLine(lineCurrent, styler))
|
||||
{
|
||||
if (!IsCommentLine(lineCurrent - 1, styler)
|
||||
&& IsCommentLine(lineCurrent + 1, styler))
|
||||
@ -563,7 +671,7 @@ void FoldPascalDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, W
|
||||
&& !IsCommentLine(lineCurrent+1, styler))
|
||||
levelCurrent--;
|
||||
}
|
||||
if (foldPreprocessor) {
|
||||
if (options.foldPreprocessor) {
|
||||
if (style == SCE_PAS_PREPROCESSOR && ch == '{' && chNext == '$') {
|
||||
ClassifyPascalPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 2, styler);
|
||||
} else if (style == SCE_PAS_PREPROCESSOR2 && ch == '(' && chNext == '*'
|
||||
@ -588,14 +696,14 @@ void FoldPascalDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, W
|
||||
|
||||
if (atEOL) {
|
||||
int lev = levelPrev;
|
||||
if (visibleChars == 0 && foldCompact)
|
||||
if (visibleChars == 0 && options.foldCompact)
|
||||
lev |= SC_FOLDLEVELWHITEFLAG;
|
||||
if ((levelCurrent > levelPrev) && (visibleChars > 0))
|
||||
lev |= SC_FOLDLEVELHEADERFLAG;
|
||||
if (lev != styler.LevelAt(lineCurrent)) {
|
||||
styler.SetLevel(lineCurrent, lev);
|
||||
}
|
||||
int newLineState = (styler.GetLineState(lineCurrent) & ~stateFoldMaskAll) | lineFoldStateCurrent;
|
||||
const int newLineState = (styler.GetLineState(lineCurrent) & ~stateFoldMaskAll) | lineFoldStateCurrent;
|
||||
styler.SetLineState(lineCurrent, newLineState);
|
||||
lineCurrent++;
|
||||
levelPrev = levelCurrent;
|
||||
@ -606,16 +714,11 @@ void FoldPascalDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, W
|
||||
// If we didn't reach the EOL in previous loop, store line level and whitespace information.
|
||||
// The rest will be filled in later...
|
||||
int lev = levelPrev;
|
||||
if (visibleChars == 0 && foldCompact)
|
||||
if (visibleChars == 0 && options.foldCompact)
|
||||
lev |= SC_FOLDLEVELWHITEFLAG;
|
||||
styler.SetLevel(lineCurrent, lev);
|
||||
}
|
||||
|
||||
const char * const pascalWordListDesc[] = {
|
||||
"Keywords",
|
||||
0
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
extern const LexerModule lmPascal(SCLEX_PASCAL, ColourisePascalDoc, "pascal", FoldPascalDoc, pascalWordListDesc);
|
||||
extern const LexerModule lmPascal(SCLEX_PASCAL, LexerPascal::LexerFactoryPascal, "pascal", pascalWordListDesc);
|
||||
|
||||
@ -454,16 +454,38 @@ const LexicalClass lexicalClasses[] = {
|
||||
29, "SCE_PL_STRING_QR", "literal regex", "qr = regex",
|
||||
30, "SCE_PL_STRING_QW", "literal string interpolated", "qw = array",
|
||||
31, "SCE_PL_POD_VERB", "data", "pod: verbatim paragraphs",
|
||||
32, "", "predefined", "",
|
||||
33, "", "predefined", "",
|
||||
34, "", "predefined", "",
|
||||
35, "", "predefined", "",
|
||||
36, "", "predefined", "",
|
||||
37, "", "predefined", "",
|
||||
38, "", "predefined", "",
|
||||
39, "", "predefined", "",
|
||||
40, "SCE_PL_SUB_PROTOTYPE", "identifier", "subroutine prototype",
|
||||
41, "SCE_PL_FORMAT_IDENT", "identifier", "format identifier",
|
||||
42, "SCE_PL_FORMAT", "literal string", "format body",
|
||||
43, "SCE_PL_STRING_VAR", "identifier interpolated", "double quoted string (interpolated variable)",
|
||||
44, "SCE_PL_XLAT", "literal string", "translation: tr{}{} y{}{}",
|
||||
45, "", "unused", "",
|
||||
46, "", "unused", "",
|
||||
47, "", "unused", "",
|
||||
48, "", "unused", "",
|
||||
49, "", "unused", "",
|
||||
50, "", "unused", "",
|
||||
51, "", "unused", "",
|
||||
52, "", "unused", "",
|
||||
53, "", "unused", "",
|
||||
54, "SCE_PL_REGEX_VAR", "identifier interpolated", "regex: /re/ or m{re} (interpolated variable)",
|
||||
55, "SCE_PL_REGSUBST_VAR", "identifier interpolated", "substitution: s/re/ore/ (interpolated variable)",
|
||||
56, "", "unused", "",
|
||||
57, "SCE_PL_BACKTICKS_VAR", "identifier interpolated", "back ticks (interpolated variable)",
|
||||
58, "", "unused", "",
|
||||
59, "", "unused", "",
|
||||
60, "", "unused", "",
|
||||
61, "SCE_PL_HERE_QQ_VAR", "identifier interpolated", "here-doc (double quoted, qq) (interpolated variable)",
|
||||
62, "SCE_PL_HERE_QX_VAR", "identifier interpolated", "here-doc (back ticks, qx) (interpolated variable)",
|
||||
63, "", "unused", "",
|
||||
64, "SCE_PL_STRING_QQ_VAR", "identifier interpolated", "qq = double quoted string (interpolated variable)",
|
||||
65, "SCE_PL_STRING_QX_VAR", "identifier interpolated", "qx = back ticks (interpolated variable)",
|
||||
66, "SCE_PL_STRING_QR_VAR", "identifier interpolated", "qr = regex (interpolated variable)",
|
||||
|
||||
@ -147,6 +147,14 @@ const LexicalClass lexicalClasses[] = {
|
||||
29, "SCE_RB_WORD_DEMOTED", "keyword", "Keyword demoted",
|
||||
30, "SCE_RB_STDIN", "file", "Standard input stream",
|
||||
31, "SCE_RB_STDOUT", "file", "Standard output stream",
|
||||
32, "", "predefined", "",
|
||||
33, "", "predefined", "",
|
||||
34, "", "predefined", "",
|
||||
35, "", "predefined", "",
|
||||
36, "", "predefined", "",
|
||||
37, "", "predefined", "",
|
||||
38, "", "predefined", "",
|
||||
39, "", "predefined", "",
|
||||
40, "SCE_RB_STDERR", "file", "Standard error stream",
|
||||
41, "SCE_RB_STRING_W", "literal string", "String array",
|
||||
42, "SCE_RB_STRING_I", "literal string", "Symbol array",
|
||||
|
||||
@ -60,7 +60,8 @@ int Accessor::IndentAmount(Sci_Position line, int *flags, PFNIsCommentLeader pfn
|
||||
spaceFlags |= wsTab;
|
||||
if (spaceFlags & wsSpace)
|
||||
spaceFlags |= wsSpaceTab;
|
||||
indent = (indent / 8 + 1) * 8;
|
||||
constexpr int defaultTabSpaces = 8;
|
||||
indent = (indent / defaultTabSpaces + 1) * defaultTabSpaces;
|
||||
}
|
||||
ch = (*this)[++pos];
|
||||
}
|
||||
@ -71,6 +72,5 @@ int Accessor::IndentAmount(Sci_Position line, int *flags, PFNIsCommentLeader pfn
|
||||
if ((LineStart(line) == Length()) || (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') ||
|
||||
(pfnIsCommentLeader && (*pfnIsCommentLeader)(*this, pos, end-pos)))
|
||||
return indent | SC_FOLDLEVELWHITEFLAG;
|
||||
else
|
||||
return indent;
|
||||
return indent;
|
||||
}
|
||||
|
||||
@ -4285,18 +4285,16 @@ bool IsIdContinue(int character) noexcept {
|
||||
bool IsXidStart(int character) noexcept {
|
||||
if (OmitXidStart(character)) {
|
||||
return false;
|
||||
} else {
|
||||
return IsIdStart(character);
|
||||
}
|
||||
return IsIdStart(character);
|
||||
}
|
||||
|
||||
// XID_Continue is ID_Continue modified for Normalization Form KC in UAX #31
|
||||
bool IsXidContinue(int character) noexcept {
|
||||
if (OmitXidContinue(character)) {
|
||||
return false;
|
||||
} else {
|
||||
return IsIdContinue(character);
|
||||
}
|
||||
return IsIdContinue(character);
|
||||
}
|
||||
|
||||
CharacterCategoryMap::CharacterCategoryMap() {
|
||||
|
||||
@ -12,7 +12,9 @@ namespace Lexilla {
|
||||
|
||||
template<int N>
|
||||
class CharacterSetArray {
|
||||
unsigned char bset[(N-1)/8 + 1] = {};
|
||||
static constexpr int bitsPerChar = 8;
|
||||
static constexpr int mask3Bits = 7;
|
||||
unsigned char bset[((N-1)/bitsPerChar) + 1] = {};
|
||||
bool valueAfter = false;
|
||||
public:
|
||||
enum setBase {
|
||||
@ -23,7 +25,7 @@ public:
|
||||
setAlpha=setLower|setUpper,
|
||||
setAlphaNum=setAlpha|setDigits
|
||||
};
|
||||
CharacterSetArray(setBase base=setNone, const char *initialSet="", bool valueAfter_=false) noexcept {
|
||||
explicit CharacterSetArray(setBase base=setNone, const char *initialSet="", bool valueAfter_=false) noexcept {
|
||||
valueAfter = valueAfter_;
|
||||
AddString(initialSet);
|
||||
if (base & setLower)
|
||||
@ -33,7 +35,7 @@ public:
|
||||
if (base & setDigits)
|
||||
AddString("0123456789");
|
||||
}
|
||||
CharacterSetArray(const char *initialSet, bool valueAfter_=false) noexcept :
|
||||
explicit CharacterSetArray(const char *initialSet, bool valueAfter_=false) noexcept :
|
||||
CharacterSetArray(setNone, initialSet, valueAfter_) {
|
||||
}
|
||||
// For compatibility with previous version but should not be used in new code.
|
||||
@ -44,7 +46,7 @@ public:
|
||||
void Add(int val) noexcept {
|
||||
assert(val >= 0);
|
||||
assert(val < N);
|
||||
bset[val >> 3] |= 1 << (val & 7);
|
||||
bset[val >> 3] |= 1 << (val & mask3Bits);
|
||||
}
|
||||
void AddString(const char *setToAdd) noexcept {
|
||||
for (const char *cp=setToAdd; *cp; cp++) {
|
||||
@ -53,20 +55,21 @@ public:
|
||||
Add(uch);
|
||||
}
|
||||
}
|
||||
bool Contains(int val) const noexcept {
|
||||
[[nodiscard]] bool Contains(int val) const noexcept {
|
||||
assert(val >= 0);
|
||||
if (val < 0) return false;
|
||||
if (val >= N) return valueAfter;
|
||||
return bset[val >> 3] & (1 << (val & 7));
|
||||
return bset[val >> 3] & (1 << (val & mask3Bits));
|
||||
}
|
||||
bool Contains(char ch) const noexcept {
|
||||
[[nodiscard]] bool Contains(char ch) const noexcept {
|
||||
// Overload char as char may be signed
|
||||
const unsigned char uch = ch;
|
||||
return Contains(uch);
|
||||
}
|
||||
};
|
||||
|
||||
using CharacterSet = CharacterSetArray<0x80>;
|
||||
constexpr int countASCII = 0x80;
|
||||
using CharacterSet = CharacterSetArray<countASCII>;
|
||||
|
||||
// Functions for classifying characters
|
||||
|
||||
@ -84,8 +87,11 @@ constexpr void AnyOf([[maybe_unused]] T *t, [[maybe_unused]] Args... args) noexc
|
||||
template <typename T, typename... Args>
|
||||
constexpr void AnyOf([[maybe_unused]] const T *t, [[maybe_unused]] Args... args) noexcept {}
|
||||
|
||||
constexpr int charTab = 0x09;
|
||||
constexpr int charCarriageReturn = 0x0D;
|
||||
|
||||
constexpr bool IsASpace(int ch) noexcept {
|
||||
return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
|
||||
return (ch == ' ') || ((ch >= charTab) && (ch <= charCarriageReturn));
|
||||
}
|
||||
|
||||
constexpr bool IsASpaceOrTab(int ch) noexcept {
|
||||
@ -107,17 +113,18 @@ constexpr bool IsAnOctalDigit(int ch) noexcept {
|
||||
}
|
||||
|
||||
constexpr bool IsADigit(int ch, int base) noexcept {
|
||||
if (base <= 10) {
|
||||
constexpr int digits = 10;
|
||||
if (base <= digits) {
|
||||
return (ch >= '0') && (ch < '0' + base);
|
||||
} else {
|
||||
return ((ch >= '0') && (ch <= '9')) ||
|
||||
((ch >= 'A') && (ch < 'A' + base - 10)) ||
|
||||
((ch >= 'a') && (ch < 'a' + base - 10));
|
||||
}
|
||||
return ((ch >= '0') && (ch <= '9')) ||
|
||||
((ch >= 'A') && (ch < 'A' + base - digits)) ||
|
||||
((ch >= 'a') && (ch < 'a' + base - digits));
|
||||
}
|
||||
|
||||
constexpr bool IsASCII(int ch) noexcept {
|
||||
return (ch >= 0) && (ch < 0x80);
|
||||
constexpr int lastASCII = 0x7F;
|
||||
return (ch >= 0) && (ch <= lastASCII);
|
||||
}
|
||||
|
||||
constexpr bool IsLowerCase(int ch) noexcept {
|
||||
@ -144,7 +151,7 @@ constexpr bool IsAlphaNumeric(int ch) noexcept {
|
||||
* This is ASCII specific but is safe with chars >= 0x80.
|
||||
*/
|
||||
constexpr bool isspacechar(int ch) noexcept {
|
||||
return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
|
||||
return (ch == ' ') || ((ch >= charTab) && (ch <= charCarriageReturn));
|
||||
}
|
||||
|
||||
constexpr bool iswordchar(int ch) noexcept {
|
||||
@ -174,16 +181,14 @@ template <typename T>
|
||||
constexpr T MakeUpperCase(T ch) noexcept {
|
||||
if (ch < 'a' || ch > 'z')
|
||||
return ch;
|
||||
else
|
||||
return ch - 'a' + 'A';
|
||||
return ch - 'a' + 'A';
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
constexpr T MakeLowerCase(T ch) noexcept {
|
||||
if (ch < 'A' || ch > 'Z')
|
||||
return ch;
|
||||
else
|
||||
return ch - 'A' + 'a';
|
||||
return ch - 'A' + 'a';
|
||||
}
|
||||
|
||||
int CompareCaseInsensitive(const char *a, const char *b) noexcept;
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <map>
|
||||
|
||||
#include "ILexer.h"
|
||||
#include "Scintilla.h"
|
||||
@ -21,6 +22,7 @@
|
||||
#include "LexAccessor.h"
|
||||
#include "Accessor.h"
|
||||
#include "LexerModule.h"
|
||||
#include "OptionSet.h"
|
||||
#include "DefaultLexer.h"
|
||||
|
||||
using namespace Lexilla;
|
||||
@ -46,14 +48,20 @@ int SCI_METHOD DefaultLexer::Version() const {
|
||||
}
|
||||
|
||||
const char * SCI_METHOD DefaultLexer::PropertyNames() {
|
||||
if (osi)
|
||||
return osi->PropertyNames();
|
||||
return "";
|
||||
}
|
||||
|
||||
int SCI_METHOD DefaultLexer::PropertyType(const char *) {
|
||||
int SCI_METHOD DefaultLexer::PropertyType(const char *name) {
|
||||
if (osi)
|
||||
return osi->PropertyType(name);
|
||||
return SC_TYPE_BOOLEAN;
|
||||
}
|
||||
|
||||
const char * SCI_METHOD DefaultLexer::DescribeProperty(const char *) {
|
||||
const char * SCI_METHOD DefaultLexer::DescribeProperty(const char *name) {
|
||||
if (osi)
|
||||
return osi->DescribeProperty(name);
|
||||
return "";
|
||||
}
|
||||
|
||||
@ -62,6 +70,8 @@ Sci_Position SCI_METHOD DefaultLexer::PropertySet(const char *, const char *) {
|
||||
}
|
||||
|
||||
const char * SCI_METHOD DefaultLexer::DescribeWordListSets() {
|
||||
if (osi)
|
||||
return osi->DescribeWordListSets();
|
||||
return "";
|
||||
}
|
||||
|
||||
@ -139,6 +149,8 @@ int SCI_METHOD DefaultLexer::GetIdentifier() {
|
||||
return language;
|
||||
}
|
||||
|
||||
const char *SCI_METHOD DefaultLexer::PropertyGet(const char * /* key */) {
|
||||
const char *SCI_METHOD DefaultLexer::PropertyGet(const char *key) {
|
||||
if (osi)
|
||||
return osi->PropertyGet(key);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -12,16 +12,23 @@
|
||||
|
||||
namespace Lexilla {
|
||||
|
||||
struct OptionSetInterface; // Forward declaration
|
||||
|
||||
// A simple lexer with no state
|
||||
class DefaultLexer : public Scintilla::ILexer5 {
|
||||
const char *languageName;
|
||||
int language;
|
||||
const LexicalClass *lexClasses;
|
||||
size_t nClasses;
|
||||
OptionSetInterface *osi = nullptr;
|
||||
public:
|
||||
DefaultLexer(const char *languageName_, int language_,
|
||||
const LexicalClass *lexClasses_ = nullptr, size_t nClasses_ = 0);
|
||||
virtual ~DefaultLexer();
|
||||
void SetOptionSet(OptionSetInterface *osi_) noexcept {
|
||||
this->osi = osi_;
|
||||
}
|
||||
|
||||
void SCI_METHOD Release() override;
|
||||
int SCI_METHOD Version() const override;
|
||||
const char * SCI_METHOD PropertyNames() override;
|
||||
|
||||
@ -65,9 +65,8 @@ const char * SCI_METHOD LexerBase::DescribeProperty(const char *) {
|
||||
Sci_Position SCI_METHOD LexerBase::PropertySet(const char *key, const char *val) {
|
||||
if (props.Set(key, val)) {
|
||||
return 0;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *SCI_METHOD LexerBase::PropertyGet(const char *key) {
|
||||
|
||||
@ -17,7 +17,7 @@ protected:
|
||||
size_t nClasses;
|
||||
PropSetSimple props;
|
||||
enum {numWordLists=KEYWORDSET_MAX+1};
|
||||
WordList *keyWordLists[numWordLists+1];
|
||||
WordList *keyWordLists[numWordLists+1]{};
|
||||
public:
|
||||
LexerBase(const LexicalClass *lexClasses_=nullptr, size_t nClasses_=0);
|
||||
virtual ~LexerBase();
|
||||
|
||||
@ -63,24 +63,22 @@ int LexerModule::GetLanguage() const noexcept {
|
||||
int LexerModule::GetNumWordLists() const noexcept {
|
||||
if (!wordListDescriptions) {
|
||||
return -1;
|
||||
} else {
|
||||
int numWordLists = 0;
|
||||
|
||||
while (wordListDescriptions[numWordLists]) {
|
||||
++numWordLists;
|
||||
}
|
||||
|
||||
return numWordLists;
|
||||
}
|
||||
int numWordLists = 0;
|
||||
|
||||
while (wordListDescriptions[numWordLists]) {
|
||||
++numWordLists;
|
||||
}
|
||||
|
||||
return numWordLists;
|
||||
}
|
||||
|
||||
const char *LexerModule::GetWordListDescription(int index) const noexcept {
|
||||
assert(index < GetNumWordLists());
|
||||
if (!wordListDescriptions || (index >= GetNumWordLists())) {
|
||||
return "";
|
||||
} else {
|
||||
return wordListDescriptions[index];
|
||||
}
|
||||
return wordListDescriptions[index];
|
||||
}
|
||||
|
||||
const LexicalClass *LexerModule::LexClasses() const noexcept {
|
||||
@ -94,8 +92,7 @@ size_t LexerModule::NamedStyles() const noexcept {
|
||||
Scintilla::ILexer5 *LexerModule::Create() const {
|
||||
if (fnFactory)
|
||||
return fnFactory();
|
||||
else
|
||||
return new LexerSimple(this);
|
||||
return new LexerSimple(this);
|
||||
}
|
||||
|
||||
void LexerModule::Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle,
|
||||
|
||||
@ -12,12 +12,33 @@
|
||||
|
||||
namespace Lexilla {
|
||||
|
||||
inline std::string JoinWordListDescriptions(const char *const wordListDescriptions[]) {
|
||||
std::string wordLists;
|
||||
if (wordListDescriptions) {
|
||||
for (size_t wl = 0; wordListDescriptions[wl]; wl++) {
|
||||
if (wl > 0)
|
||||
wordLists += "\n";
|
||||
wordLists += wordListDescriptions[wl];
|
||||
}
|
||||
}
|
||||
return wordLists;
|
||||
}
|
||||
|
||||
// Allow OptionSet<T> to be called without knowing T
|
||||
struct OptionSetInterface {
|
||||
[[nodiscard]] virtual const char *PropertyNames() const noexcept = 0;
|
||||
[[nodiscard]] virtual int PropertyType(const char *name) const = 0;
|
||||
[[nodiscard]] virtual const char *DescribeProperty(const char *name) const = 0;
|
||||
[[nodiscard]] virtual const char *PropertyGet(const char *name) const = 0;
|
||||
[[nodiscard]] virtual const char *DescribeWordListSets() const noexcept = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
class OptionSet {
|
||||
typedef T Target;
|
||||
typedef bool T::*plcob;
|
||||
typedef int T::*plcoi;
|
||||
typedef std::string T::*plcos;
|
||||
class OptionSet : public OptionSetInterface {
|
||||
using Target = T;
|
||||
using plcob = bool T::*;
|
||||
using plcoi = int T::*;
|
||||
using plcos = std::string T::*;
|
||||
struct Option {
|
||||
int opType;
|
||||
union {
|
||||
@ -70,11 +91,11 @@ class OptionSet {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
const char *Get() const noexcept {
|
||||
[[nodiscard]] const char *Get() const noexcept {
|
||||
return value.c_str();
|
||||
}
|
||||
};
|
||||
typedef std::map<std::string, Option, std::less<>> OptionMap;
|
||||
using OptionMap = std::map<std::string, Option, std::less<>> ;
|
||||
OptionMap nameToDef;
|
||||
std::string names;
|
||||
std::string wordLists;
|
||||
@ -85,6 +106,8 @@ class OptionSet {
|
||||
names += name;
|
||||
}
|
||||
public:
|
||||
virtual ~OptionSet() = default;
|
||||
|
||||
void DefineProperty(const char *name, plcob pb, std::string_view description="") {
|
||||
nameToDef[name] = Option(pb, description);
|
||||
AppendName(name);
|
||||
@ -106,17 +129,17 @@ public:
|
||||
nameToDef[name] = Option(pi, description);
|
||||
AppendName(name);
|
||||
}
|
||||
const char *PropertyNames() const noexcept {
|
||||
[[nodiscard]] const char *PropertyNames() const noexcept final {
|
||||
return names.c_str();
|
||||
}
|
||||
int PropertyType(const char *name) const {
|
||||
[[nodiscard]] int PropertyType(const char *name) const final {
|
||||
typename OptionMap::const_iterator const it = nameToDef.find(name);
|
||||
if (it != nameToDef.end()) {
|
||||
return it->second.opType;
|
||||
}
|
||||
return SC_TYPE_BOOLEAN;
|
||||
}
|
||||
const char *DescribeProperty(const char *name) const {
|
||||
[[nodiscard]] const char *DescribeProperty(const char *name) const final {
|
||||
typename OptionMap::const_iterator const it = nameToDef.find(name);
|
||||
if (it != nameToDef.end()) {
|
||||
return it->second.description.c_str();
|
||||
@ -132,7 +155,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *PropertyGet(const char *name) const {
|
||||
[[nodiscard]] const char *PropertyGet(const char *name) const final {
|
||||
typename OptionMap::const_iterator const it = nameToDef.find(name);
|
||||
if (it != nameToDef.end()) {
|
||||
return it->second.Get();
|
||||
@ -141,16 +164,10 @@ public:
|
||||
}
|
||||
|
||||
void DefineWordListSets(const char * const wordListDescriptions[]) {
|
||||
if (wordListDescriptions) {
|
||||
for (size_t wl = 0; wordListDescriptions[wl]; wl++) {
|
||||
if (wl > 0)
|
||||
wordLists += "\n";
|
||||
wordLists += wordListDescriptions[wl];
|
||||
}
|
||||
}
|
||||
wordLists = JoinWordListDescriptions(wordListDescriptions);
|
||||
}
|
||||
|
||||
const char *DescribeWordListSets() const noexcept {
|
||||
[[nodiscard]] const char *DescribeWordListSets() const noexcept final {
|
||||
return wordLists.c_str();
|
||||
}
|
||||
};
|
||||
|
||||
@ -62,7 +62,7 @@ public:
|
||||
}
|
||||
}
|
||||
bool Delete(Sci_Position position) {
|
||||
typename stateVector::iterator low = Find(position);
|
||||
const typename stateVector::iterator low = Find(position);
|
||||
if (low != states.end()) {
|
||||
states.erase(low, states.end());
|
||||
return true;
|
||||
@ -80,7 +80,7 @@ public:
|
||||
|
||||
bool different = true;
|
||||
bool changed = false;
|
||||
typename stateVector::iterator low = Find(other.positionFirst);
|
||||
const typename stateVector::iterator low = Find(other.positionFirst);
|
||||
if (static_cast<size_t>(states.end() - low) == other.states.size()) {
|
||||
// Same number in other as after positionFirst in this
|
||||
different = !std::equal(low, states.end(), other.states.begin());
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
# LexillaData.py - implemented 2013 by Neil Hodgson neilh@scintilla.org
|
||||
# Released to the public domain.
|
||||
# Requires FileGenerator from Scintilla so scintilla must be a peer directory of lexilla.
|
||||
|
||||
"""
|
||||
Common code used by Lexilla and SciTE for source file regeneration.
|
||||
@ -59,7 +58,7 @@ def FindModules(lexFile):
|
||||
partLine = ""
|
||||
with lexFile.open(encoding=neutralEncoding) as f:
|
||||
lineNum = 0
|
||||
for line in f.readlines():
|
||||
for line in f:
|
||||
lineNum += 1
|
||||
line = line.rstrip()
|
||||
if partLine or line.startswith("extern const LexerModule"):
|
||||
@ -162,7 +161,7 @@ def FindProperties(lexFile):
|
||||
""" Return a set of property names in a lexer implementation file. """
|
||||
properties = set()
|
||||
with open(lexFile, encoding=neutralEncoding) as f:
|
||||
for s in f.readlines():
|
||||
for s in f:
|
||||
if ("GetProperty" in s or "DefineProperty" in s) and "\"" in s:
|
||||
s = s.strip()
|
||||
if not s.startswith("//"): # Drop comments
|
||||
@ -180,7 +179,7 @@ def FindPropertyDocumentation(lexFile):
|
||||
documents = {}
|
||||
with lexFile.open(encoding=neutralEncoding) as f:
|
||||
name = ""
|
||||
for line in f.readlines():
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if "// property " in line:
|
||||
propertyName = line.split()[2]
|
||||
@ -219,19 +218,19 @@ def FindPropertyDocumentation(lexFile):
|
||||
|
||||
def FindCredits(historyFile):
|
||||
""" Return a list of contributors in a history file. """
|
||||
creditList = []
|
||||
credits = []
|
||||
stage = 0
|
||||
with historyFile.open(encoding="utf-8") as f:
|
||||
for line in f.readlines():
|
||||
line = line.strip()
|
||||
if stage == 0 and line == "<table>":
|
||||
for line in f:
|
||||
s = line.strip()
|
||||
if stage == 0 and s == "<table>":
|
||||
stage = 1
|
||||
elif stage == 1 and line == "</table>":
|
||||
elif stage == 1 and s == "</table>":
|
||||
stage = 2
|
||||
if stage == 1 and line.startswith("<td>"):
|
||||
credit = line[4:-5]
|
||||
if "<a" in line:
|
||||
title, dummy, rest = credit.partition("<a href=")
|
||||
if stage == 1 and s.startswith("<td>"):
|
||||
credit = s[4:-5]
|
||||
if "<a" in s:
|
||||
title, _, rest = credit.partition("<a href=")
|
||||
urlplus, _bracket, end = rest.partition(">")
|
||||
name = end.split("<")[0]
|
||||
url = urlplus[1:-1]
|
||||
@ -239,8 +238,8 @@ def FindCredits(historyFile):
|
||||
if credit:
|
||||
credit += " "
|
||||
credit += name + " " + url
|
||||
creditList.append(credit)
|
||||
return creditList
|
||||
credits.append(credit)
|
||||
return credits
|
||||
|
||||
def ciKey(a):
|
||||
""" Return a string lowered to be used when sorting. """
|
||||
@ -261,7 +260,7 @@ class LexillaData:
|
||||
self.versionCommad = self.versionDotted.replace(".", ", ") + ', 0'
|
||||
|
||||
with (scintillaRoot / "doc" / "Lexilla.html").open() as f:
|
||||
self.dateModified = [d for d in f.readlines() if "Date.Modified" in d]\
|
||||
self.dateModified = [d for d in f if "Date.Modified" in d]\
|
||||
[0].split('\"')[3]
|
||||
# 20130602
|
||||
# Lexilla.html
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>5.4.7</string>
|
||||
<string>5.4.8</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
|
||||
@ -900,7 +900,7 @@
|
||||
buildSettings = {
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 5.4.7;
|
||||
CURRENT_PROJECT_VERSION = 5.4.8;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = 4F446KW87E;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
@ -928,7 +928,7 @@
|
||||
buildSettings = {
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 5.4.7;
|
||||
CURRENT_PROJECT_VERSION = 5.4.8;
|
||||
DEAD_CODE_STRIPPING = YES;
|
||||
DEVELOPMENT_TEAM = 4F446KW87E;
|
||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||
|
||||
@ -4,8 +4,8 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#define VERSION_LEXILLA "5.4.7"
|
||||
#define VERSION_WORDS 5, 4, 7, 0
|
||||
#define VERSION_LEXILLA "5.4.8"
|
||||
#define VERSION_WORDS 5, 4, 8, 0
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VERSION_WORDS
|
||||
|
||||
1107
lexilla/src/deps.mak
1107
lexilla/src/deps.mak
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1 +1 @@
|
||||
547
|
||||
548
|
||||
@ -26,9 +26,9 @@
|
||||
<table bgcolor="#CCCCCC" width="100%" cellspacing="0" cellpadding="8" border="0">
|
||||
<tr>
|
||||
<td>
|
||||
<font size="4"> <a href="https://www.scintilla.org/scintilla560.zip">
|
||||
<font size="4"> <a href="https://www.scintilla.org/scintilla561.zip">
|
||||
Windows</a>
|
||||
<a href="https://www.scintilla.org/scintilla560.tgz">
|
||||
<a href="https://www.scintilla.org/scintilla561.tgz">
|
||||
GTK/Linux</a>
|
||||
</font>
|
||||
</td>
|
||||
@ -42,7 +42,7 @@
|
||||
containing very few restrictions.
|
||||
</p>
|
||||
<h3>
|
||||
Release 5.6.0
|
||||
Release 5.6.1
|
||||
</h3>
|
||||
<h4>
|
||||
Source Code
|
||||
@ -50,8 +50,8 @@
|
||||
The source code package contains all of the source code for Scintilla but no binary
|
||||
executable code and is available in
|
||||
<ul>
|
||||
<li><a href="https://www.scintilla.org/scintilla560.zip">zip format</a> (1.8M) commonly used on Windows</li>
|
||||
<li><a href="https://www.scintilla.org/scintilla560.tgz">tgz format</a> (1.7M) commonly used on Linux and compatible operating systems</li>
|
||||
<li><a href="https://www.scintilla.org/scintilla561.zip">zip format</a> (1.8M) commonly used on Windows</li>
|
||||
<li><a href="https://www.scintilla.org/scintilla561.tgz">tgz format</a> (1.7M) commonly used on Linux and compatible operating systems</li>
|
||||
</ul>
|
||||
Instructions for building on both Windows and Linux are included in the readme file.
|
||||
<h4>
|
||||
|
||||
@ -603,7 +603,7 @@
|
||||
</h3>
|
||||
<ul>
|
||||
<li>
|
||||
Released 25 February 2026.
|
||||
Released 26 March 2026.
|
||||
</li>
|
||||
<li>
|
||||
Add mode to draw tabs as [HT] blobs with SCI_SETTABDRAWMODE(SCTD_CONTROLCHAR).
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<meta name="keywords" content="Scintilla, SciTE, Editing Component, Text Editor" />
|
||||
<meta name="Description"
|
||||
content="www.scintilla.org is the home of the Scintilla editing component and SciTE text editor application." />
|
||||
<meta name="Date.Modified" content="20260225" />
|
||||
<meta name="Date.Modified" content="20260326" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<style type="text/css">
|
||||
.logo {
|
||||
@ -61,8 +61,8 @@
|
||||
GTK, and macOS</font>
|
||||
</td>
|
||||
<td width="40%" align="right">
|
||||
<font color="#FFCC99" size="3"> Release version 5.6.0<br />
|
||||
Site last modified February 25 2026</font>
|
||||
<font color="#FFCC99" size="3"> Release version 5.6.1<br />
|
||||
Site last modified March 26 2026</font>
|
||||
</td>
|
||||
<td width="20%">
|
||||
|
||||
@ -77,12 +77,11 @@
|
||||
</tr>
|
||||
</table>
|
||||
<ul id="versionlist">
|
||||
<li>Version 5.6.1 adds mode to draw tabs as HT blobs and fixes a regression in SCI_CONVERTEOLS.</li>
|
||||
<li>Version 5.6.0 fixes crash when window is too narrow to show any text.</li>
|
||||
<li>Version 5.5.9 adds an option to disable drag & drop. Fixes colour after line end.</li>
|
||||
<li>Version 5.5.8 changes format of SCI_GETSELECTIONSERIALIZED and fixes redraw after undo.</li>
|
||||
<li>Version 5.5.7 can prevent storing scroll position in undo selection history and adds a wrap-aware SCI_SCROLLVERTICAL API.</li>
|
||||
<li>Version 5.5.6 improves DBCS and autocompletion drawing on Win32 and improves dwell, encoding and text clipping on Qt.</li>
|
||||
<li>Version 5.5.5 can remember selection with undo and redo. Update to use DirectWrite 1.1.</li>
|
||||
</ul>
|
||||
<ul id="menu">
|
||||
<li id="remote1"><a href="https://www.scintilla.org/SciTEImage.html">Screenshot</a></li>
|
||||
|
||||
@ -35,13 +35,13 @@ def depunctuate(s):
|
||||
|
||||
symbols = {}
|
||||
with open(incFileName, "rt") as incFile:
|
||||
for line in incFile.readlines():
|
||||
for line in incFile:
|
||||
if line.startswith("#define"):
|
||||
identifier = line.split()[1]
|
||||
symbols[identifier] = 0
|
||||
|
||||
with open(docFileName, "rt") as docFile:
|
||||
for line in docFile.readlines():
|
||||
for line in docFile:
|
||||
for word in depunctuate(line).split():
|
||||
if word in symbols.keys():
|
||||
symbols[word] = 1
|
||||
|
||||
@ -17,9 +17,10 @@
|
||||
# Only tested with ASCII file names.
|
||||
# Copyright 2019 by Neil Hodgson <neilh@scintilla.org>
|
||||
# The License.txt file describes the conditions under which this software may be distributed.
|
||||
# Requires Python 2.7 or later
|
||||
# Requires Python 3.6 or later
|
||||
|
||||
import codecs, glob, os, sys
|
||||
from functools import cache
|
||||
|
||||
if __name__ == "__main__":
|
||||
import FileGenerator
|
||||
@ -28,6 +29,7 @@ else:
|
||||
|
||||
continuationLineEnd = " \\"
|
||||
|
||||
@cache
|
||||
def FindPathToHeader(header, includePath):
|
||||
for incDir in includePath:
|
||||
relPath = os.path.join(incDir, header)
|
||||
@ -35,27 +37,25 @@ def FindPathToHeader(header, includePath):
|
||||
return relPath
|
||||
return ""
|
||||
|
||||
fhifCache = {} # Remember the includes in each file. ~5x speed up.
|
||||
@cache
|
||||
def FindHeadersInFile(filePath):
|
||||
if filePath not in fhifCache:
|
||||
headers = []
|
||||
with codecs.open(filePath, "r", "utf-8") as f:
|
||||
for line in f:
|
||||
if line.strip().startswith("#include"):
|
||||
parts = line.split()
|
||||
if len(parts) > 1:
|
||||
header = parts[1]
|
||||
if header[0] != '<': # No system headers
|
||||
headers.append(header.strip('"'))
|
||||
fhifCache[filePath] = headers
|
||||
return fhifCache[filePath]
|
||||
headers = []
|
||||
with codecs.open(filePath, "r", "utf-8") as f:
|
||||
for line in f:
|
||||
if line.strip().startswith("#include"):
|
||||
parts = line.split()
|
||||
if len(parts) > 1:
|
||||
header = parts[1]
|
||||
if header[0] != '<': # No system headers
|
||||
headers.append(header.strip('"'))
|
||||
return headers
|
||||
|
||||
def FindHeadersInFileRecursive(filePath, includePath, renames):
|
||||
headerPaths = []
|
||||
for header in FindHeadersInFile(filePath):
|
||||
if header in renames:
|
||||
header = renames[header]
|
||||
relPath = FindPathToHeader(header, includePath)
|
||||
relPath = FindPathToHeader(header, tuple(includePath))
|
||||
if relPath and relPath not in headerPaths:
|
||||
headerPaths.append(relPath)
|
||||
subHeaders = FindHeadersInFileRecursive(relPath, includePath, renames)
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
# Face.py - module for reading and parsing Scintilla.iface file
|
||||
# Implemented 2000 by Neil Hodgson neilh@scintilla.org
|
||||
# Released to the public domain.
|
||||
# Requires Python 2.7 or later
|
||||
# Requires Python 3.6 or later
|
||||
|
||||
def sanitiseLine(line):
|
||||
line = line.rstrip('\n')
|
||||
@ -72,7 +72,7 @@ class Face:
|
||||
currentComment = []
|
||||
currentCommentFinished = 0
|
||||
file = open(name)
|
||||
for line in file.readlines():
|
||||
for line in file:
|
||||
line = sanitiseLine(line)
|
||||
if line:
|
||||
if line[0] == "#":
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
# Generate or regenerate source files based on comments in those files.
|
||||
# May be modified in-place or a template may be generated into a complete file.
|
||||
# Requires Python 2.7 or later
|
||||
# Requires Python 3.6 or later
|
||||
# The files are copied to a string apart from sections between a
|
||||
# ++Autogenerated comment and a --Autogenerated comment which is
|
||||
# generated by the CopyWithInsertion function. After the whole string is
|
||||
@ -143,7 +143,7 @@ def UpdateLineInPlistFile(path, key, value):
|
||||
lines = []
|
||||
keyCurrent = ""
|
||||
with codecs.open(path, "rb", "utf-8") as f:
|
||||
for line in f.readlines():
|
||||
for line in f:
|
||||
ls = line.strip()
|
||||
if ls.startswith("<key>"):
|
||||
keyCurrent = ls.replace("<key>", "").replace("</key>", "")
|
||||
@ -160,7 +160,7 @@ def UpdateLineInFile(path, linePrefix, lineReplace):
|
||||
lines = []
|
||||
updated = False
|
||||
with codecs.open(path, "r", "utf-8") as f:
|
||||
for line in f.readlines():
|
||||
for line in f:
|
||||
line = line.rstrip()
|
||||
if not updated and line.startswith(linePrefix):
|
||||
lines.append(lineReplace)
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
# Script to generate scintilla/src/CharacterCategoryMap.cxx and lexilla/lexlib/CharacterCategory.cxx
|
||||
# from Python's Unicode data
|
||||
# Should be run rarely when a Python with a new version of Unicode data is available.
|
||||
# Requires Python 3.3 or later
|
||||
# Requires Python 3.6 or later
|
||||
# Should not be run with old versions of Python.
|
||||
|
||||
import pathlib, platform, sys, unicodedata
|
||||
@ -11,7 +11,7 @@ from FileGenerator import Regenerate
|
||||
|
||||
def findCategories(filename):
|
||||
with filename.open(encoding="UTF-8") as infile:
|
||||
lines = [x.strip() for x in infile.readlines() if "\tcc" in x]
|
||||
lines = [x.strip() for x in infile if "\tcc" in x]
|
||||
values = "".join(lines).replace(" ","").split(",")
|
||||
print("Categrories:", values)
|
||||
return [v[2:] for v in values]
|
||||
|
||||
@ -25,19 +25,20 @@
|
||||
import datetime, pathlib, sys
|
||||
|
||||
def FindCredits(historyFile, removeLinks=True):
|
||||
""" Return a list of contributors in a history file. """
|
||||
credits = []
|
||||
stage = 0
|
||||
with historyFile.open(encoding="utf-8") as f:
|
||||
for line in f.readlines():
|
||||
line = line.strip()
|
||||
if stage == 0 and line == "<table>":
|
||||
for line in f:
|
||||
s = line.strip()
|
||||
if stage == 0 and s == "<table>":
|
||||
stage = 1
|
||||
elif stage == 1 and line == "</table>":
|
||||
elif stage == 1 and s == "</table>":
|
||||
stage = 2
|
||||
if stage == 1 and line.startswith("<td>"):
|
||||
credit = line[4:-5]
|
||||
if removeLinks and "<a" in line:
|
||||
title, _a, rest = credit.partition("<a href=")
|
||||
if stage == 1 and s.startswith("<td>"):
|
||||
credit = s[4:-5]
|
||||
if removeLinks and "<a" in s:
|
||||
title, _, rest = credit.partition("<a href=")
|
||||
urlplus, _bracket, end = rest.partition(">")
|
||||
name = end.split("<")[0]
|
||||
url = urlplus[1:-1]
|
||||
@ -57,14 +58,14 @@ class ScintillaData:
|
||||
self.versionCommad = self.versionDotted.replace(".", ", ") + ', 0'
|
||||
|
||||
with (scintillaRoot / "doc" / "index.html").open() as f:
|
||||
self.dateModified = [d for d in f.readlines() if "Date.Modified" in d]\
|
||||
self.dateModified = [d for d in f if "Date.Modified" in d]\
|
||||
[0].split('\"')[3]
|
||||
# 20130602
|
||||
# index.html, SciTE.html
|
||||
dtModified = datetime.datetime.strptime(self.dateModified, "%Y%m%d")
|
||||
self.yearModified = self.dateModified[0:4]
|
||||
monthModified = dtModified.strftime("%B")
|
||||
dayModified = "%d" % dtModified.day
|
||||
dayModified = f"{dtModified.day}"
|
||||
self.mdyModified = monthModified + " " + dayModified + " " + self.yearModified
|
||||
# May 22 2013
|
||||
# index.html, SciTE.html
|
||||
|
||||
@ -1 +1 @@
|
||||
560
|
||||
561
|
||||
|
||||
@ -6,8 +6,8 @@
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#define VERSION_SCINTILLA "5.6.0"
|
||||
#define VERSION_WORDS 5, 6, 0, 0
|
||||
#define VERSION_SCINTILLA "5.6.1"
|
||||
#define VERSION_WORDS 5, 6, 1, 0
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION VERSION_WORDS
|
||||
|
||||
Loading…
Reference in New Issue
Block a user