mirror of
https://github.com/notepad-plus-plus/notepad-plus-plus.git
synced 2025-08-26 04:08:26 +02:00
Release 5.5.7 (https://www.scintilla.org/scintilla557.zip) Released 8 June 2025 1. Add SCI_SCROLLVERTICAL method to restore view position and maintain it while performing line wrapping. 2. Add SC_UNDO_SELECTION_HISTORY_SCROLL flag to SCI_SETUNDOSELECTIONHISTORY which controls whether undo and redo restore vertical scroll position. 3. Tweak SC_MARK_BAR to be slightly wider by using next higher whole pixel instead of next lower for margin width / 3. 4. Scale images in autocompletion lists with SCI_AUTOCSETIMAGESCALE to match high DPI screens. Initially only on GTK and Qt. 5. Fix wrapping bug for UTF-8 where \r\n could wrap between the characters. Notepad++ Pull Request #16373. 6. Fix crash during painting when scroll bars changed. Bug #2481. 7. On GTK, reset vertical scroll bar synchronously in SCI_SETDOCPOINTER to fix bug where scroll position not restored in non-wrap mode. Bug #2416. 8. On GTK, fix IME problem when tentative composition interfered with delete surrounding. Feature #1476. 9. On GTK, update IME cursor position inside retrieve surrounding to better position candidate window. Feature #1488. Release 5.4.5 (https://www.scintilla.org/lexilla545.zip) Released 8 June 2025 1. Dart: Add error state SCE_DART_STRINGEOL for unterminated string. Pull request #315. 2. Makefile: Add a keyword list to makefile lexer to highlight GNU Make directives like 'ifdef' and 'vpath' as SCE_MAKE_PREPROCESSOR since these are similar to NMAKE directives like '!IFDEF'. 3. Nix: Add error state SCE_NIX_STRINGEOL for unterminated string. Pull request #315. 4. TOML: Add error state SCE_TOML_STRINGEOL for unterminated string. Pull request #315. 5. Zig: Add error state SCE_ZIG_STRINGEOL for unterminated string. Pull request #315. Close #16649
541 lines
14 KiB
C++
541 lines
14 KiB
C++
// Scintilla source code edit control
|
|
/** @file LexNix.cxx
|
|
** Lexer for Nix.
|
|
**/
|
|
// Based on Zufu Liu's Notepad4 Dart lexer
|
|
// Modified for Nix and Scintilla by Jiri Techet, 2024
|
|
// The License.txt file describes the conditions under which this software may be distributed.
|
|
|
|
#include <cassert>
|
|
#include <cstring>
|
|
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <vector>
|
|
#include <map>
|
|
#include <algorithm>
|
|
|
|
#include "ILexer.h"
|
|
#include "Scintilla.h"
|
|
#include "SciLexer.h"
|
|
|
|
#include "WordList.h"
|
|
#include "LexAccessor.h"
|
|
#include "Accessor.h"
|
|
#include "StyleContext.h"
|
|
#include "CharacterSet.h"
|
|
#include "LexerModule.h"
|
|
#include "OptionSet.h"
|
|
#include "DefaultLexer.h"
|
|
|
|
using namespace Scintilla;
|
|
using namespace Lexilla;
|
|
|
|
namespace {
|
|
// Use an unnamed namespace to protect the functions and classes from name conflicts
|
|
|
|
constexpr bool IsAGraphic(int ch) noexcept {
|
|
// excludes C0 control characters and whitespace
|
|
return ch > 32 && ch < 127;
|
|
}
|
|
|
|
constexpr bool IsIdentifierChar(int ch) noexcept {
|
|
return IsAlphaNumeric(ch) || ch == '_' || ch == '\'' || ch == '-';
|
|
}
|
|
|
|
constexpr bool IsIdentifierStart(int ch) noexcept {
|
|
return IsUpperOrLowerCase(ch) || ch == '_';
|
|
}
|
|
|
|
constexpr bool IsNumberContinue(int chPrev, int ch, int chNext) noexcept {
|
|
return ((ch == '+' || ch == '-') && (chPrev == 'e' || chPrev == 'E'))
|
|
|| (ch == '.' && chNext != '.');
|
|
}
|
|
|
|
constexpr bool IsNumberStart(int ch, int chNext) noexcept {
|
|
return IsADigit(ch) || (ch == '.' && IsADigit(chNext));
|
|
}
|
|
|
|
constexpr bool IsDecimalNumber(int chPrev, int ch, int chNext) noexcept {
|
|
return IsIdentifierChar(ch) || IsNumberContinue(chPrev, ch, chNext);
|
|
}
|
|
|
|
constexpr bool IsNixIdentifierStart(int ch) noexcept {
|
|
return IsIdentifierStart(ch);
|
|
}
|
|
|
|
constexpr bool IsNixIdentifierChar(int ch) noexcept {
|
|
return IsIdentifierChar(ch);
|
|
}
|
|
|
|
constexpr bool IsPathTerminator(int ch) noexcept {
|
|
return isspacechar(ch) || AnyOf(ch, ';', ',', ']', '}', ')');
|
|
}
|
|
|
|
bool IsKey(LexAccessor &styler, Sci_Position start) {
|
|
for (Sci_Position i = 0; i < 50; i++) {
|
|
char curr = styler.SafeGetCharAt(start+i, '\0');
|
|
char next = styler.SafeGetCharAt(start+i+1, '\0');
|
|
bool atEOL = (curr == '\r' && next != '\n') || (curr == '\n') || (curr == '\0');
|
|
if (curr == '=') {
|
|
return true;
|
|
} else if (!isspacechar(curr) || atEOL) {
|
|
return false;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
bool IsPath(LexAccessor &styler, Sci_Position start) {
|
|
for (Sci_Position i = 0; i < 50; i++) {
|
|
char curr = styler.SafeGetCharAt(start+i, '\0');
|
|
char next = styler.SafeGetCharAt(start+i+1, '\0');
|
|
bool atEOL = (curr == '\r' && next != '\n') || (curr == '\n') || (curr == '\0');
|
|
if (curr == '/') {
|
|
return true;
|
|
} else if (IsPathTerminator(curr) || curr == '$' || atEOL) {
|
|
return false;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
enum {
|
|
NixLineStateMaskInterpolation = 1, // string interpolation
|
|
};
|
|
|
|
// string interpolating state
|
|
struct InterpolatingState {
|
|
int state;
|
|
int braceCount;
|
|
};
|
|
|
|
// Options used for LexerNix
|
|
struct OptionsNix {
|
|
bool fold = false;
|
|
};
|
|
|
|
const char * const nixWordListDesc[] = {
|
|
"Keywords 1",
|
|
"Keywords 2",
|
|
"Keywords 3",
|
|
"Keywords 4",
|
|
nullptr
|
|
};
|
|
|
|
struct OptionSetNix : public OptionSet<OptionsNix> {
|
|
OptionSetNix() {
|
|
DefineProperty("fold", &OptionsNix::fold);
|
|
|
|
DefineWordListSets(nixWordListDesc);
|
|
}
|
|
};
|
|
|
|
|
|
LexicalClass lexicalClasses[] = {
|
|
// Lexer NIX SCLEX_NIX SCE_NIX_:
|
|
0, "SCE_NIX_DEFAULT", "default", "White space",
|
|
1, "SCE_NIX_COMMENTLINE", "comment line", "Comment: //",
|
|
2, "SCE_NIX_COMMENTBLOCK", "comment", "Comment: /* */",
|
|
3, "SCE_NIX_STRING", "literal string", "Double quoted string",
|
|
4, "SCE_NIX_STRING_MULTILINE", "literal string multiline", "Single quoted multiline string",
|
|
5, "SCE_NIX_ESCAPECHAR", "literal string escapesequence", "Escape sequence",
|
|
6, "SCE_NIX_IDENTIFIER", "identifier", "Identifier",
|
|
7, "SCE_NIX_OPERATOR", "operator", "Operator",
|
|
8, "SCE_NIX_OPERATOR_STRING", "operator interpolated", "Braces following $ inside string",
|
|
9, "SCE_NIX_NUMBER", "literal numeric", "Number",
|
|
10, "SCE_NIX_KEY", "key", "Keys preceding '='",
|
|
11, "SCE_NIX_PATH", "identifier", "Path literal",
|
|
12, "SCE_NIX_KEYWORD1", "keyword", "Primary keywords",
|
|
13, "SCE_NIX_KEYWORD2", "identifier", "Keywords 2",
|
|
14, "SCE_NIX_KEYWORD3", "identifier", "Keywords 3",
|
|
15, "SCE_NIX_KEYWORD4", "identifier", "Keywords 4",
|
|
16, "SCE_NIX_STRINGEOL", "error literal string", "End of line where string is not closed",
|
|
};
|
|
|
|
class LexerNix : public DefaultLexer {
|
|
WordList keywordsPrimary;
|
|
WordList keywordsSecondary;
|
|
WordList keywordsTertiary;
|
|
WordList keywordsTypes;
|
|
OptionsNix options;
|
|
OptionSetNix osNix;
|
|
public:
|
|
LexerNix(const char *languageName_, int language_) :
|
|
DefaultLexer(languageName_, language_, lexicalClasses, std::size(lexicalClasses)) {
|
|
}
|
|
// Deleted so LexerNix objects can not be copied.
|
|
LexerNix(const LexerNix &) = delete;
|
|
LexerNix(LexerNix &&) = delete;
|
|
void operator=(const LexerNix &) = delete;
|
|
void operator=(LexerNix &&) = delete;
|
|
~LexerNix() override = default;
|
|
|
|
void SCI_METHOD Release() override {
|
|
delete this;
|
|
}
|
|
int SCI_METHOD Version() const override {
|
|
return lvRelease5;
|
|
}
|
|
const char *SCI_METHOD PropertyNames() override {
|
|
return osNix.PropertyNames();
|
|
}
|
|
int SCI_METHOD PropertyType(const char *name) override {
|
|
return osNix.PropertyType(name);
|
|
}
|
|
const char *SCI_METHOD DescribeProperty(const char *name) override {
|
|
return osNix.DescribeProperty(name);
|
|
}
|
|
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
|
|
const char *SCI_METHOD PropertyGet(const char *key) override {
|
|
return osNix.PropertyGet(key);
|
|
}
|
|
const char *SCI_METHOD DescribeWordListSets() override {
|
|
return osNix.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;
|
|
}
|
|
|
|
void BacktrackToStart(const LexAccessor &styler, int stateMask, Sci_PositionU &startPos, Sci_Position &lengthDoc, int &initStyle);
|
|
|
|
static ILexer5 *LexerFactoryNix() {
|
|
return new LexerNix("nix", SCLEX_NIX);
|
|
}
|
|
};
|
|
|
|
Sci_Position SCI_METHOD LexerNix::PropertySet(const char *key, const char *val) {
|
|
if (osNix.PropertySet(&options, key, val)) {
|
|
return 0;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
Sci_Position SCI_METHOD LexerNix::WordListSet(int n, const char *wl) {
|
|
WordList *wordListN = nullptr;
|
|
switch (n) {
|
|
case 0:
|
|
wordListN = &keywordsPrimary;
|
|
break;
|
|
case 1:
|
|
wordListN = &keywordsSecondary;
|
|
break;
|
|
case 2:
|
|
wordListN = &keywordsTertiary;
|
|
break;
|
|
case 3:
|
|
wordListN = &keywordsTypes;
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
Sci_Position firstModification = -1;
|
|
if (wordListN && wordListN->Set(wl/*, false*/)) {
|
|
firstModification = 0;
|
|
}
|
|
return firstModification;
|
|
}
|
|
|
|
void LexerNix::BacktrackToStart(const LexAccessor &styler, int stateMask, Sci_PositionU &startPos, Sci_Position &lengthDoc, int &initStyle) {
|
|
const Sci_Position currentLine = styler.GetLine(startPos);
|
|
if (currentLine != 0) {
|
|
Sci_Position line = currentLine - 1;
|
|
int lineState = styler.GetLineState(line);
|
|
while ((lineState & stateMask) != 0 && line != 0) {
|
|
--line;
|
|
lineState = styler.GetLineState(line);
|
|
}
|
|
if ((lineState & stateMask) == 0) {
|
|
++line;
|
|
}
|
|
if (line != currentLine) {
|
|
const Sci_PositionU endPos = startPos + lengthDoc;
|
|
startPos = (line == 0) ? 0 : styler.LineStart(line);
|
|
lengthDoc = endPos - startPos;
|
|
initStyle = (startPos == 0) ? 0 : styler.StyleAt(startPos - 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
void LexerNix::Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, IDocument *pAccess) {
|
|
Accessor styler(pAccess, nullptr);
|
|
|
|
std::vector<InterpolatingState> interpolatingStack;
|
|
|
|
if (initStyle == SCE_NIX_STRINGEOL) {
|
|
initStyle = SCE_NIX_DEFAULT;
|
|
}
|
|
|
|
if (startPos != 0) {
|
|
// backtrack to the line where interpolation starts
|
|
BacktrackToStart(styler, NixLineStateMaskInterpolation, startPos, lengthDoc, initStyle);
|
|
}
|
|
|
|
StyleContext sc(startPos, lengthDoc, initStyle, styler);
|
|
|
|
while (sc.More()) {
|
|
switch (sc.state) {
|
|
case SCE_NIX_OPERATOR:
|
|
case SCE_NIX_OPERATOR_STRING:
|
|
sc.SetState(SCE_NIX_DEFAULT);
|
|
break;
|
|
|
|
case SCE_NIX_NUMBER:
|
|
if (!IsDecimalNumber(sc.chPrev, sc.ch, sc.chNext)) {
|
|
sc.SetState(SCE_NIX_DEFAULT);
|
|
}
|
|
break;
|
|
|
|
case SCE_NIX_IDENTIFIER:
|
|
if (sc.state == SCE_NIX_IDENTIFIER && !IsNixIdentifierChar(sc.ch)) {
|
|
char s[64];
|
|
sc.GetCurrent(s, sizeof(s));
|
|
if (IsKey(styler, sc.currentPos)) {
|
|
sc.ChangeState(SCE_NIX_KEY);
|
|
} else if (keywordsPrimary.InList(s)) {
|
|
sc.ChangeState(SCE_NIX_KEYWORD1);
|
|
} else if (keywordsSecondary.InList(s)) {
|
|
sc.ChangeState(SCE_NIX_KEYWORD2);
|
|
} else if (keywordsTertiary.InList(s)) {
|
|
sc.ChangeState(SCE_NIX_KEYWORD3);
|
|
} else if (keywordsTypes.InList(s)) {
|
|
sc.ChangeState(SCE_NIX_KEYWORD4);
|
|
}
|
|
|
|
sc.SetState(SCE_NIX_DEFAULT);
|
|
}
|
|
break;
|
|
|
|
case SCE_NIX_COMMENTLINE:
|
|
if (sc.atLineStart) {
|
|
sc.SetState(SCE_NIX_DEFAULT);
|
|
}
|
|
break;
|
|
|
|
case SCE_NIX_COMMENTBLOCK:
|
|
if (sc.Match('*', '/')) {
|
|
sc.Forward(2);
|
|
sc.SetState(SCE_NIX_DEFAULT);
|
|
continue;
|
|
}
|
|
break;
|
|
|
|
case SCE_NIX_STRING:
|
|
if (sc.atLineStart) {
|
|
sc.SetState(SCE_NIX_DEFAULT);
|
|
} else if (sc.atLineEnd) {
|
|
sc.ChangeState(SCE_NIX_STRINGEOL);
|
|
} else if (sc.ch == '\\' && AnyOf(sc.chNext, '"', '\\', 'n', 'r', 't', '$')) {
|
|
sc.SetState(SCE_NIX_STRING);
|
|
sc.ChangeState(SCE_NIX_ESCAPECHAR);
|
|
sc.Forward(2);
|
|
sc.SetState(SCE_NIX_STRING);
|
|
continue;
|
|
} else if (sc.ch == '\"') {
|
|
sc.Forward();
|
|
sc.SetState(SCE_NIX_DEFAULT);
|
|
continue;
|
|
} else if (sc.Match('$','$')) {
|
|
sc.Forward();
|
|
continue;
|
|
}
|
|
break;
|
|
|
|
case SCE_NIX_STRINGEOL:
|
|
if (sc.atLineStart) {
|
|
sc.SetState(SCE_NIX_DEFAULT);
|
|
}
|
|
break;
|
|
|
|
case SCE_NIX_PATH:
|
|
if (sc.atLineStart) {
|
|
sc.SetState(SCE_NIX_DEFAULT);
|
|
} else if (sc.ch == '>') {
|
|
sc.Forward();
|
|
sc.SetState(SCE_NIX_DEFAULT);
|
|
continue;
|
|
} else if (IsPathTerminator(sc.ch)) {
|
|
sc.SetState(SCE_NIX_DEFAULT);
|
|
}
|
|
break;
|
|
|
|
case SCE_NIX_STRING_MULTILINE:
|
|
if (sc.ch == '\'' && sc.chNext == '\'') {
|
|
if (AnyOf(styler.SafeGetCharAt(sc.currentPos+2, '\0'), '$', '\'', '\\')) {
|
|
sc.SetState(SCE_NIX_ESCAPECHAR);
|
|
sc.Forward(2);
|
|
if (sc.ch == '$' || sc.ch == '\'') {
|
|
sc.Forward();
|
|
} else if (sc.ch == '\\') {
|
|
sc.Forward(2);
|
|
}
|
|
sc.SetState(SCE_NIX_STRING_MULTILINE);
|
|
continue;
|
|
} else {
|
|
sc.Forward(2);
|
|
sc.SetState(SCE_NIX_DEFAULT);
|
|
continue;
|
|
}
|
|
} else if (sc.Match('$','$')) {
|
|
sc.Forward();
|
|
continue;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (sc.state == SCE_NIX_DEFAULT)
|
|
{
|
|
if (sc.ch == '/' && sc.chNext == '*') {
|
|
sc.SetState(SCE_NIX_COMMENTBLOCK);
|
|
sc.Forward();
|
|
continue;
|
|
} else if (sc.ch == '#') {
|
|
sc.SetState(SCE_NIX_COMMENTLINE);
|
|
} else if (sc.ch == '"') {
|
|
sc.SetState(SCE_NIX_STRING);
|
|
} else if (sc.ch == '\'' && sc.chNext == '\'') {
|
|
sc.SetState(SCE_NIX_STRING_MULTILINE);
|
|
sc.Forward();
|
|
continue;
|
|
} else if (IsNumberStart(sc.ch, sc.chNext)) {
|
|
sc.SetState(SCE_NIX_NUMBER);
|
|
} else if (sc.ch == '<') {
|
|
sc.SetState(SCE_NIX_PATH);
|
|
} else if ((IsNixIdentifierStart(sc.ch) || AnyOf(sc.ch, '~', '.', '/')) &&
|
|
IsPath(styler, sc.currentPos)) {
|
|
sc.SetState(SCE_NIX_PATH);
|
|
} else if (IsNixIdentifierStart(sc.ch)) {
|
|
sc.SetState(SCE_NIX_IDENTIFIER);
|
|
} else if (IsAGraphic(sc.ch) && sc.ch != '$') {
|
|
sc.SetState(SCE_NIX_OPERATOR);
|
|
if (!interpolatingStack.empty() && AnyOf(sc.ch, '{', '}')) {
|
|
InterpolatingState ¤t = interpolatingStack.back();
|
|
if (sc.ch == '{') {
|
|
current.braceCount += 1;
|
|
} else {
|
|
current.braceCount -= 1;
|
|
if (current.braceCount == 0) {
|
|
sc.ChangeState(SCE_NIX_OPERATOR_STRING);
|
|
sc.ForwardSetState(current.state);
|
|
interpolatingStack.pop_back();
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// string interpolations
|
|
if (AnyOf(sc.state, SCE_NIX_DEFAULT, SCE_NIX_STRING, SCE_NIX_STRING_MULTILINE, SCE_NIX_PATH)) {
|
|
if (sc.Match('$','{')) {
|
|
interpolatingStack.push_back({sc.state, 1});
|
|
sc.SetState(SCE_NIX_OPERATOR_STRING);
|
|
sc.Forward();
|
|
}
|
|
}
|
|
|
|
if (sc.atLineEnd) {
|
|
int lineState = 0;
|
|
if (!interpolatingStack.empty()) {
|
|
lineState |= NixLineStateMaskInterpolation;
|
|
}
|
|
styler.SetLineState(sc.currentLine, lineState);
|
|
}
|
|
|
|
sc.Forward();
|
|
}
|
|
|
|
sc.Complete();
|
|
}
|
|
|
|
void LexerNix::Fold(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, IDocument *pAccess) {
|
|
if (!options.fold)
|
|
return;
|
|
|
|
Accessor styler(pAccess, nullptr);
|
|
const Sci_PositionU endPos = startPos + lengthDoc;
|
|
Sci_Position lineCurrent = styler.GetLine(startPos);
|
|
while (lineCurrent > 0) {
|
|
lineCurrent--;
|
|
startPos = styler.LineStart(lineCurrent);
|
|
initStyle = (startPos > 0) ? styler.StyleIndexAt(startPos) : 0;
|
|
if (!AnyOf(initStyle, SCE_NIX_COMMENTBLOCK, SCE_NIX_STRING_MULTILINE)) {
|
|
break;
|
|
}
|
|
}
|
|
int levelCurrent = SC_FOLDLEVELBASE;
|
|
if (lineCurrent > 0) {
|
|
levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16;
|
|
}
|
|
|
|
int levelNext = levelCurrent;
|
|
Sci_PositionU lineStartNext = styler.LineStart(lineCurrent + 1);
|
|
lineStartNext = std::min(lineStartNext, endPos);
|
|
|
|
char chNext = styler[startPos];
|
|
int styleNext = styler.StyleIndexAt(startPos);
|
|
int style = initStyle;
|
|
|
|
while (startPos < endPos) {
|
|
const char ch = chNext;
|
|
const int stylePrev = style;
|
|
style = styleNext;
|
|
chNext = styler[++startPos];
|
|
styleNext = styler.StyleIndexAt(startPos);
|
|
|
|
switch (style) {
|
|
case SCE_NIX_COMMENTBLOCK:
|
|
if (style != stylePrev) {
|
|
levelNext++;
|
|
}
|
|
if (style != styleNext) {
|
|
levelNext--;
|
|
}
|
|
break;
|
|
|
|
case SCE_NIX_STRING_MULTILINE:
|
|
if (style != stylePrev && !AnyOf(stylePrev, SCE_NIX_ESCAPECHAR, SCE_NIX_OPERATOR_STRING)) {
|
|
levelNext++;
|
|
}
|
|
if (style != styleNext && !AnyOf(styleNext, SCE_NIX_ESCAPECHAR, SCE_NIX_OPERATOR_STRING)) {
|
|
levelNext--;
|
|
}
|
|
break;
|
|
|
|
case SCE_NIX_OPERATOR:
|
|
case SCE_NIX_OPERATOR_STRING:
|
|
if (ch == '{' || ch == '[' || ch == '(') {
|
|
levelNext++;
|
|
} else if (ch == '}' || ch == ']' || ch == ')') {
|
|
levelNext--;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (startPos == lineStartNext) {
|
|
levelNext = std::max(levelNext, SC_FOLDLEVELBASE);
|
|
|
|
const int levelUse = levelCurrent;
|
|
int lev = levelUse | (levelNext << 16);
|
|
if (levelUse < levelNext) {
|
|
lev |= SC_FOLDLEVELHEADERFLAG;
|
|
}
|
|
styler.SetLevel(lineCurrent, lev);
|
|
|
|
lineCurrent++;
|
|
lineStartNext = styler.LineStart(lineCurrent + 1);
|
|
lineStartNext = std::min(lineStartNext, endPos);
|
|
levelCurrent = levelNext;
|
|
}
|
|
}
|
|
}
|
|
|
|
} // unnamed namespace end
|
|
|
|
extern const LexerModule lmNix(SCLEX_NIX, LexerNix::LexerFactoryNix, "nix", nixWordListDesc);
|