mirror of
https://github.com/rizonesoft/Notepad3.git
synced 2026-06-11 21:03:05 +08:00
+ add: src code for new AHK(_L) Lexer
This commit is contained in:
parent
302bb2a2f5
commit
43ef4a96a8
772
sciXlexers/LexAHKL.cxx
Normal file
772
sciXlexers/LexAHKL.cxx
Normal file
@ -0,0 +1,772 @@
|
||||
// Scintilla source code edit control
|
||||
/** @file LexAHKL.cxx
|
||||
** Lexer AutoHotkey L
|
||||
** Created by Isaias "RaptorX" Baez (graptorx@gmail.com)
|
||||
**/
|
||||
// Copyright ©2013 Isaias "RaptorX" Baez <graptorx@gmail.com> - [GPLv3]
|
||||
// The License.txt file describes the conditions under which this software may be distributed.
|
||||
// https://github.com/RaptorX/LexAHKL/
|
||||
//
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <windows.h>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include "ILexer.h"
|
||||
#include "Scintilla.h"
|
||||
#include "SciXLexer.h"
|
||||
|
||||
#include "WordList.h"
|
||||
#include "LexAccessor.h"
|
||||
#include "Accessor.h"
|
||||
#include "StyleContext.h"
|
||||
#include "CharacterSet.h"
|
||||
#include "LexerModule.h"
|
||||
#include <windows.h>
|
||||
|
||||
using namespace Scintilla;
|
||||
|
||||
static const char* const ahklWordLists[] = {
|
||||
"Directives",
|
||||
"Commands",
|
||||
"Command Parameters",
|
||||
"Control Flow",
|
||||
"Built-in Functions",
|
||||
"Built-in Variables",
|
||||
"Keyboard & Mouse Keys",
|
||||
"User Defined 1",
|
||||
"User Defined 2",
|
||||
nullptr};
|
||||
|
||||
class LexerAHKL : public ILexer4 {
|
||||
|
||||
CharacterSet valLabel;
|
||||
CharacterSet valHotkeyMod;
|
||||
CharacterSet valIdentifier;
|
||||
CharacterSet valHotstringOpt;
|
||||
CharacterSet valDocComment;
|
||||
|
||||
WordList directives;
|
||||
WordList commands;
|
||||
WordList parameters;
|
||||
WordList flow;
|
||||
WordList functions;
|
||||
WordList variables;
|
||||
WordList keys;
|
||||
WordList user1;
|
||||
WordList user2;
|
||||
|
||||
CharacterSet ExpOperator;
|
||||
CharacterSet SynOperator;
|
||||
CharacterSet EscSequence;
|
||||
|
||||
public:
|
||||
LexerAHKL() :
|
||||
//valLabel(CharacterSet::setAlphaNum, "@#$_~!^&*()+[]\';./\\<>?|{}-=\""),
|
||||
valLabel(CharacterSet::setAlphaNum, R"(@#$_~!^&*()+[]';./\<>?|{}-=")"),
|
||||
valHotkeyMod(CharacterSet::setDigits, "#!^+&<>*~$"),
|
||||
valIdentifier(CharacterSet::setAlphaNum, "@#$_"),
|
||||
valHotstringOpt(CharacterSet::setDigits, "*?BbCcEeIiKkOoPpRrSsZz"),
|
||||
valDocComment(CharacterSet::setNone, "'`\""),
|
||||
ExpOperator(CharacterSet::setNone, "+-*/!~&|^<>.:"),
|
||||
SynOperator(CharacterSet::setNone, "+-*/!~&|^<>.:()[]?,{}"),
|
||||
EscSequence(CharacterSet::setNone, ",%`;nrbtvaf")
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~LexerAHKL() = default;
|
||||
|
||||
int SCI_METHOD Version() const override { return lvRelease4;}
|
||||
void SCI_METHOD Release() override { delete this; }
|
||||
const char * SCI_METHOD PropertyNames() override { return ""; }
|
||||
int SCI_METHOD PropertyType(const char *name) override { return 0; }
|
||||
const char * SCI_METHOD DescribeProperty(const char *name) override { return ""; }
|
||||
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override { return 0;}
|
||||
const char * SCI_METHOD DescribeWordListSets() override { return ""; }
|
||||
void * SCI_METHOD PrivateCall(int, void *) override { return nullptr; }
|
||||
int SCI_METHOD LineEndTypesSupported() override { return 0; }
|
||||
int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) override { return 0; }
|
||||
int SCI_METHOD SubStylesStart(int styleBase) override { return 0; }
|
||||
int SCI_METHOD SubStylesLength(int styleBase) override { return 0; }
|
||||
int SCI_METHOD StyleFromSubStyle(int subStyle) override { return 0; }
|
||||
int SCI_METHOD PrimaryStyleFromStyle(int style) override { return 0; }
|
||||
void SCI_METHOD FreeSubStyles() override { return; }
|
||||
void SCI_METHOD SetIdentifiers(int style, const char *identifiers) override { return; }
|
||||
int SCI_METHOD DistanceToSecondaryStyles() override { return 0; }
|
||||
const char * SCI_METHOD GetSubStyleBases() override { return ""; }
|
||||
int SCI_METHOD NamedStyles() override { return 0; }
|
||||
const char * SCI_METHOD NameOfStyle(int style) override { return ""; }
|
||||
const char * SCI_METHOD TagsOfStyle(int style) override { return ""; }
|
||||
const char * SCI_METHOD DescriptionOfStyle(int style) override { return ""; }
|
||||
|
||||
|
||||
Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override;
|
||||
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, IDocument *pAccess) override;
|
||||
void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, IDocument *pAccess) override;
|
||||
|
||||
static ILexer4 *LexerFactoryAHKL() {
|
||||
return new LexerAHKL();
|
||||
}
|
||||
};
|
||||
|
||||
Sci_Position SCI_METHOD LexerAHKL::WordListSet(int n, const char *wl)
|
||||
{
|
||||
WordList *wordListN = nullptr;
|
||||
switch (n) {
|
||||
|
||||
case 0:
|
||||
wordListN = &directives;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
wordListN = &commands;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
wordListN = ¶meters;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
wordListN = &flow;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
wordListN = &functions;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
wordListN = &variables;
|
||||
break;
|
||||
|
||||
case 6:
|
||||
wordListN = &keys;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
wordListN = &user1;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
wordListN = &user2;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
int firstModification = -1;
|
||||
if (wordListN) {
|
||||
WordList wlNew;
|
||||
wlNew.Set(wl);
|
||||
if (*wordListN != wlNew) {
|
||||
wordListN->Set(wl);
|
||||
firstModification = 0;
|
||||
}
|
||||
}
|
||||
return firstModification;
|
||||
}
|
||||
|
||||
|
||||
void SCI_METHOD LexerAHKL::Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, IDocument *pAccess)
|
||||
{
|
||||
LexAccessor styler(pAccess);
|
||||
StyleContext sc(startPos, lengthDoc, initStyle, styler);
|
||||
|
||||
// non-lexical states
|
||||
int expLevel = 0;
|
||||
int mainState = SCE_AHKL_NEUTRAL; // Used on some special cases like objects where SCE_AHKL_NEUTRAL is set but
|
||||
// we basically come from SCE_AHKL_OBJECT and we need to be aware of it
|
||||
bool OnlySpaces = false;
|
||||
bool validLabel = false;
|
||||
bool validFunction = false;
|
||||
|
||||
bool inKey = false;
|
||||
bool inString = false;
|
||||
bool inCommand = false;
|
||||
bool inHotstring = false;
|
||||
bool inExpString = false;
|
||||
bool inDocComment = false;
|
||||
bool inExpression = false;
|
||||
|
||||
bool inStringBlk = (sc.state == SCE_AHKL_STRINGOPTS || sc.state == SCE_AHKL_STRINGBLOCK || sc.state == SCE_AHKL_STRINGCOMMENT);
|
||||
bool inCommentBlk = (sc.state == SCE_AHKL_COMMENTDOC || sc.state == SCE_AHKL_COMMENTBLOCK);
|
||||
|
||||
for (; sc.More(); sc.Forward()) {
|
||||
|
||||
// AutoHotkey usually resets lexical state in a per line base except in Comment and String Blocks
|
||||
if (sc.atLineStart) {
|
||||
|
||||
expLevel = 0;
|
||||
mainState = SCE_AHKL_NEUTRAL;
|
||||
|
||||
OnlySpaces = true, validLabel = true, validFunction = true, inKey = false, inString = false;
|
||||
inDocComment = false, inCommand = false, inHotstring = false, inExpression = false, inExpString = false;
|
||||
|
||||
if (!inStringBlk && !inCommentBlk)
|
||||
sc.SetState(SCE_AHKL_NEUTRAL);
|
||||
}
|
||||
|
||||
// Comments are allowed almost everywhere
|
||||
if (!inStringBlk && !inCommentBlk && (OnlySpaces || isspace(sc.chPrev)) && sc.ch == ';')
|
||||
sc.SetState(SCE_AHKL_COMMENTLINE);
|
||||
|
||||
// Exit Current State
|
||||
switch (sc.state) {
|
||||
|
||||
case SCE_AHKL_IDENTIFIER: {
|
||||
if (sc.atLineEnd || !valIdentifier.Contains(sc.ch)) { // Check for match after typing whole words or punctuation signs
|
||||
|
||||
char identifier[256];
|
||||
sc.GetCurrentLowered(identifier, sizeof(identifier));
|
||||
|
||||
if (!sc.Match('('))
|
||||
validFunction = false;
|
||||
|
||||
if (directives.InList(identifier)) {
|
||||
|
||||
sc.ChangeState(SCE_AHKL_DIRECTIVE);
|
||||
|
||||
} else if (!inExpression && !inCommand && !inKey && sc.ch != '(' && commands.InList(identifier)) {
|
||||
|
||||
inCommand = true;
|
||||
sc.ChangeState(SCE_AHKL_COMMAND);
|
||||
|
||||
} else if (inCommand && parameters.InList(identifier)) {
|
||||
|
||||
sc.ChangeState(SCE_AHKL_PARAM);
|
||||
|
||||
} else if (!inKey && flow.InList(identifier)) { // avoid conflicts with key identifiers (e.g. pause)
|
||||
|
||||
sc.ChangeState(SCE_AHKL_CONTROLFLOW);
|
||||
|
||||
} else if (sc.ch == '(' && functions.InList(identifier)) {
|
||||
|
||||
inCommand = true;
|
||||
sc.ChangeState(SCE_AHKL_BUILTINFUNCTION);
|
||||
|
||||
} else if (variables.InList(identifier)) {
|
||||
|
||||
sc.ChangeState(SCE_AHKL_BUILTINVAR);
|
||||
|
||||
} else if (inKey && keys.InList(identifier)) {
|
||||
|
||||
sc.ChangeState(SCE_AHKL_KEY);
|
||||
|
||||
} else if (user1.InList(identifier)) {
|
||||
|
||||
sc.ChangeState(SCE_AHKL_USERDEFINED1);
|
||||
|
||||
} else if (user2.InList(identifier)) {
|
||||
|
||||
sc.ChangeState(SCE_AHKL_USERDEFINED2);
|
||||
|
||||
} else if (sc.ch == '{') {
|
||||
|
||||
inKey = true; inCommand = false;
|
||||
|
||||
} else if (inExpression && !(sc.ch == '(' || sc.ch == '[' || sc.ch == '.')) { // Dont lex as a variable if it is a function or an array
|
||||
|
||||
sc.ChangeState(SCE_AHKL_VAR);
|
||||
|
||||
} else if (!inExpression && !ExpOperator.Contains(sc.chPrev) && sc.ch == '=') {
|
||||
|
||||
inString = true;
|
||||
sc.ForwardSetState(SCE_AHKL_STRING);
|
||||
|
||||
continue;
|
||||
|
||||
} else if (!inCommand && ExpOperator.Contains(sc.ch) && sc.chNext == '=') {
|
||||
|
||||
sc.SetState(SCE_AHKL_ERROR);
|
||||
|
||||
} else if (validFunction && sc.ch == '(') {
|
||||
|
||||
sc.ChangeState(SCE_AHKL_USERFUNCTION);
|
||||
sc.SetState(SCE_AHKL_NEUTRAL);
|
||||
|
||||
} else if (valLabel.Contains(sc.ch) && !(sc.ch == '(' || sc.ch == '[' || sc.ch == '.')) {
|
||||
|
||||
continue;
|
||||
|
||||
} else if (!inCommand && (sc.ch == '[' || sc.ch == '.')) {
|
||||
|
||||
if (sc.ch == '.' && valIdentifier.Contains(sc.chNext)) {
|
||||
|
||||
mainState = SCE_AHKL_OBJECT;
|
||||
|
||||
sc.ChangeState(SCE_AHKL_OBJECT);
|
||||
sc.SetState(SCE_AHKL_NEUTRAL);
|
||||
|
||||
} else if (sc.ch == '.' && !valIdentifier.Contains(sc.chNext)) {
|
||||
|
||||
sc.ChangeState(SCE_AHKL_ERROR);
|
||||
sc.SetState(SCE_AHKL_ERROR);
|
||||
|
||||
break;
|
||||
|
||||
} else if (sc.ch == '[') {
|
||||
|
||||
sc.ChangeState(SCE_AHKL_OBJECT);
|
||||
sc.SetState(SCE_AHKL_NEUTRAL);
|
||||
|
||||
}
|
||||
|
||||
} else if (mainState == SCE_AHKL_OBJECT) { // Special object case
|
||||
|
||||
mainState = SCE_AHKL_NEUTRAL;
|
||||
|
||||
if (sc.ch == '(') {
|
||||
|
||||
sc.ChangeState(SCE_AHKL_USERFUNCTION);
|
||||
sc.SetState(SCE_AHKL_NEUTRAL);
|
||||
|
||||
} else {
|
||||
|
||||
sc.ChangeState(SCE_AHKL_VAR);
|
||||
sc.SetState(SCE_AHKL_NEUTRAL);
|
||||
|
||||
}
|
||||
|
||||
} else if (!validLabel && sc.ch == ':') {
|
||||
|
||||
sc.ChangeState(SCE_AHKL_IDENTIFIER);
|
||||
|
||||
} else if (sc.ch == ':' && sc.chNext != ':' && sc.chNext != '/' && sc.chNext != '\\') {
|
||||
|
||||
sc.ChangeState(SCE_AHKL_LABEL);
|
||||
if ((sc.chNext != '\r') && (sc.chNext != '\n'))
|
||||
sc.ForwardSetState(SCE_AHKL_ERROR);
|
||||
|
||||
break;
|
||||
|
||||
} else if (!inHotstring && sc.ch == ':' && sc.chNext == ':') {
|
||||
|
||||
sc.ChangeState(SCE_AHKL_HOTKEY);
|
||||
sc.Forward(2);
|
||||
sc.SetState(SCE_AHKL_NEUTRAL);
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
validLabel = false;
|
||||
sc.SetState(SCE_AHKL_NEUTRAL);
|
||||
|
||||
} else if ((sc.chPrev == 'x' || sc.chPrev == 'y'|| sc.chPrev == 'w'|| sc.chPrev == 'h')
|
||||
&& inCommand && isdigit(sc.ch) ) { // Special number cases when entering sizes
|
||||
|
||||
sc.SetState(SCE_AHKL_DECNUMBER);
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SCE_AHKL_COMMENTDOC: {
|
||||
if (OnlySpaces && sc.Match('*','/')) {
|
||||
|
||||
inCommentBlk = false;
|
||||
sc.Forward(2);
|
||||
sc.SetState(SCE_AHKL_NEUTRAL);
|
||||
|
||||
} else if ((OnlySpaces || isspace(sc.chPrev)) &&
|
||||
((sc.ch == '@' && isalnum(sc.chNext)) || valDocComment.Contains(sc.ch))) {
|
||||
|
||||
if (valDocComment.Contains(sc.ch))
|
||||
inDocComment = true;
|
||||
|
||||
sc.SetState(SCE_AHKL_COMMENTKEYWORD);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCE_AHKL_COMMENTKEYWORD: {
|
||||
if (sc.atLineStart || (!inDocComment && sc.ch == ':')
|
||||
|| (inDocComment && valDocComment.Contains(sc.ch)))
|
||||
sc.ForwardSetState(SCE_AHKL_COMMENTDOC);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCE_AHKL_COMMENTBLOCK: {
|
||||
if (OnlySpaces && sc.Match('*','/')) {
|
||||
|
||||
inCommentBlk = false;
|
||||
sc.Forward(2);
|
||||
sc.SetState(SCE_AHKL_NEUTRAL);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCE_AHKL_HEXNUMBER: {
|
||||
if (isspace(sc.ch) || SynOperator.Contains(sc.ch))
|
||||
sc.SetState(SCE_AHKL_NEUTRAL);
|
||||
|
||||
else if (!isxdigit(sc.ch))
|
||||
sc.ChangeState(SCE_AHKL_IDENTIFIER);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCE_AHKL_DECNUMBER: {
|
||||
if (!isdigit(sc.ch)) {
|
||||
|
||||
if (sc.ch == 'x' || sc.ch == 'X')
|
||||
sc.ChangeState(SCE_AHKL_HEXNUMBER);
|
||||
|
||||
else if (isalpha(sc.ch))
|
||||
sc.ChangeState(SCE_AHKL_IDENTIFIER);
|
||||
|
||||
else
|
||||
sc.SetState(SCE_AHKL_NEUTRAL);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCE_AHKL_STRING: {
|
||||
if (inExpression && sc.atLineEnd) {
|
||||
|
||||
sc.ChangeState(SCE_AHKL_ERROR);
|
||||
|
||||
} else if (inExpression && sc.ch == '"') {
|
||||
|
||||
if (sc.chNext == '"') { // In expression string, double quotes are doubled to escape them so skip it
|
||||
|
||||
sc.Forward();
|
||||
|
||||
} else {
|
||||
|
||||
inExpString = false;
|
||||
sc.ForwardSetState(SCE_AHKL_NEUTRAL);
|
||||
|
||||
}
|
||||
|
||||
} else if (!inExpression && sc.ch == '%' && valIdentifier.Contains(sc.chNext)) {
|
||||
|
||||
sc.SetState(SCE_AHKL_NEUTRAL);
|
||||
sc.ForwardSetState(SCE_AHKL_VAR);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCE_AHKL_STRINGOPTS: {
|
||||
if (sc.atLineStart)
|
||||
sc.SetState(SCE_AHKL_STRINGBLOCK);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCE_AHKL_STRINGBLOCK: {
|
||||
if (OnlySpaces && sc.ch == ')') {
|
||||
|
||||
inStringBlk = false;
|
||||
sc.SetState(SCE_AHKL_NEUTRAL);
|
||||
|
||||
if (sc.chNext != ',')
|
||||
sc.ForwardSetState(SCE_AHKL_ERROR);
|
||||
else
|
||||
inCommand = true;
|
||||
}
|
||||
|
||||
// if ((OnlySpaces || isspace(sc.chPrev)) && sc.Match(';')) {
|
||||
|
||||
// sc.SetState(SCE_AHKL_STRINGCOMMENT);
|
||||
|
||||
// }
|
||||
break;
|
||||
}
|
||||
|
||||
case SCE_AHKL_ESCAPESEQ: {
|
||||
sc.ForwardSetState(SCE_AHKL_NEUTRAL);
|
||||
break;
|
||||
}
|
||||
|
||||
case SCE_AHKL_VAR: {
|
||||
if (!valIdentifier.Contains(sc.ch) && sc.ch != '%') {
|
||||
|
||||
sc.ChangeState(SCE_AHKL_ERROR);
|
||||
|
||||
} else if (sc.ch == '%') {
|
||||
|
||||
sc.SetState(SCE_AHKL_NEUTRAL);
|
||||
sc.ForwardSetState(SCE_AHKL_NEUTRAL);
|
||||
|
||||
if (inString )
|
||||
sc.ForwardSetState(SCE_AHKL_STRING);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCE_AHKL_VARREF: {
|
||||
if (!valIdentifier.Contains(sc.ch) && sc.ch != '%') {
|
||||
|
||||
sc.ChangeState(SCE_AHKL_ERROR);
|
||||
|
||||
} else if (sc.ch == '%') {
|
||||
|
||||
sc.SetState(SCE_AHKL_NEUTRAL);
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case SCE_AHKL_HOTSTRINGOPT: {
|
||||
if (sc.ch == ':') {
|
||||
|
||||
sc.ForwardSetState(SCE_AHKL_HOTSTRING);
|
||||
|
||||
} else if (!valHotstringOpt.Contains(sc.ch)) {
|
||||
|
||||
sc.SetState(SCE_AHKL_ERROR);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCE_AHKL_HOTSTRING: {
|
||||
if (sc.Match(':',':')) {
|
||||
|
||||
sc.SetState(SCE_AHKL_HOTSTRINGOPT);
|
||||
sc.Forward(2);
|
||||
sc.SetState(SCE_AHKL_STRING);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SCE_AHKL_ERROR: {
|
||||
if (inExpression && inExpString && sc.ch == '"') {
|
||||
|
||||
sc.ChangeState(SCE_AHKL_STRING);
|
||||
|
||||
} else if (sc.ch == '%') {
|
||||
|
||||
sc.SetState(SCE_AHKL_NEUTRAL);
|
||||
|
||||
} else if (inHotstring && valHotstringOpt.Contains(sc.ch)) {
|
||||
|
||||
sc.SetState(SCE_AHKL_HOTSTRINGOPT);
|
||||
|
||||
} else if (inHotstring && sc.ch == ':') {
|
||||
|
||||
sc.SetState(SCE_AHKL_HOTSTRINGOPT);
|
||||
sc.ForwardSetState(SCE_AHKL_HOTSTRING);
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Enter New State
|
||||
if (sc.state == SCE_AHKL_NEUTRAL) {
|
||||
|
||||
// Handle Expressions
|
||||
if ((OnlySpaces && sc.ch == '.') || sc.Match(" % ") || (sc.ch == '(')
|
||||
|| ((valIdentifier.Contains(sc.chPrev) || isspace(sc.chPrev)) && sc.ch == '?')
|
||||
|| ((valIdentifier.Contains(sc.chPrev) || isspace(sc.chPrev)) && ExpOperator.Contains(sc.ch) && sc.chNext == '=')
|
||||
|| (valIdentifier.Contains(sc.chPrev) && sc.ch == '[')) {
|
||||
|
||||
expLevel += 1;
|
||||
inExpression = true;
|
||||
|
||||
if (sc.Match(" % "))
|
||||
inCommand = false;
|
||||
|
||||
} else if (sc.ch == ']' || sc.ch == ')') {
|
||||
|
||||
expLevel -= 1, inCommand = false;
|
||||
|
||||
if (expLevel == 0)
|
||||
inExpression = false;
|
||||
|
||||
}
|
||||
|
||||
// Handle Command continuation section
|
||||
if ((OnlySpaces && sc.ch == ',') || (OnlySpaces && sc.Match(')', ',')))
|
||||
inCommand = true;
|
||||
|
||||
if ((!sc.atLineEnd && valIdentifier.Contains(sc.ch))
|
||||
|| (!inExpression && valHotkeyMod.Contains(sc.ch) && sc.chNext != '=')) {
|
||||
|
||||
if (valIdentifier.Contains(sc.ch))
|
||||
validFunction = true;
|
||||
|
||||
if (isdigit(sc.ch))
|
||||
sc.SetState(SCE_AHKL_DECNUMBER);
|
||||
|
||||
else if (inCommand && sc.ch == '+')
|
||||
continue;
|
||||
|
||||
else
|
||||
sc.SetState(SCE_AHKL_IDENTIFIER);
|
||||
|
||||
} else if (OnlySpaces && sc.Match('/', '*')) {
|
||||
|
||||
inCommentBlk = true;
|
||||
sc.ChangeState(SCE_AHKL_COMMENTBLOCK);
|
||||
|
||||
if (sc.Match("/**") && !sc.Match("/***"))
|
||||
sc.ChangeState(SCE_AHKL_COMMENTDOC);
|
||||
|
||||
} else if (sc.ch == ']') {
|
||||
|
||||
mainState = SCE_AHKL_NEUTRAL; // Reset object state
|
||||
|
||||
} else if (sc.ch == ')') {
|
||||
|
||||
// inCommand = false;
|
||||
|
||||
} else if (sc.ch == '{') {
|
||||
|
||||
inKey = true; inCommand = false;
|
||||
|
||||
} else if (sc.ch == '}') {
|
||||
|
||||
inKey = false;
|
||||
|
||||
} else if (sc.ch == '`' && EscSequence.Contains(sc.chNext)) {
|
||||
|
||||
sc.SetState(SCE_AHKL_ESCAPESEQ);
|
||||
|
||||
} else if (inExpression && sc.ch == '"') {
|
||||
|
||||
inExpString = true; inString = false;
|
||||
sc.SetState(SCE_AHKL_STRING);
|
||||
|
||||
} else if (!inExpression && !ExpOperator.Contains(sc.chPrev) && sc.ch == '=') {
|
||||
|
||||
inString = true;
|
||||
sc.ForwardSetState(SCE_AHKL_STRING);
|
||||
|
||||
} else if (OnlySpaces && sc.ch == '(') {
|
||||
|
||||
inStringBlk = true;
|
||||
sc.ForwardSetState(SCE_AHKL_STRINGOPTS);
|
||||
|
||||
} else if (!inExpression && sc.ch == '%' && valIdentifier.Contains(sc.chNext)) {
|
||||
|
||||
sc.ForwardSetState(SCE_AHKL_VAR);
|
||||
|
||||
} else if (inExpression && sc.ch == '%' && valIdentifier.Contains(sc.chNext)) {
|
||||
|
||||
sc.ForwardSetState(SCE_AHKL_VARREF);
|
||||
|
||||
} else if (OnlySpaces && sc.ch == ':') {
|
||||
|
||||
inHotstring = true;
|
||||
sc.SetState(SCE_AHKL_HOTSTRINGOPT);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!isspace(sc.ch))
|
||||
OnlySpaces = false;
|
||||
|
||||
}
|
||||
|
||||
sc.Complete();
|
||||
}
|
||||
|
||||
|
||||
void SCI_METHOD LexerAHKL::Fold(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, IDocument *pAccess)
|
||||
{
|
||||
LexAccessor styler(pAccess);
|
||||
|
||||
int visibleChars = 0;
|
||||
int lineCurrent = styler.GetLine(startPos);
|
||||
int levelCurrent = SC_FOLDLEVELBASE;
|
||||
int styleNext = styler.StyleAt(startPos);
|
||||
int style = initStyle;
|
||||
Sci_PositionU endPos = startPos + lengthDoc;
|
||||
|
||||
char chNext = styler[startPos];
|
||||
|
||||
bool OnlySpaces = true;
|
||||
|
||||
if (lineCurrent > 0)
|
||||
levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
|
||||
unsigned int lineStartNext = styler.LineStart(lineCurrent+1);
|
||||
int levelMinCurrent = levelCurrent;
|
||||
int levelNext = levelCurrent;
|
||||
|
||||
for (Sci_PositionU i = startPos; i < endPos; i++)
|
||||
{
|
||||
//int stylePrev = style;
|
||||
|
||||
char ch = chNext;
|
||||
|
||||
bool atEOL = i == (lineStartNext-2);
|
||||
|
||||
style = styleNext;
|
||||
chNext = styler.SafeGetCharAt(i + 1);
|
||||
styleNext = styler.StyleAt(i + 1);
|
||||
|
||||
if ((OnlySpaces && ch == '/' && chNext == '*'))
|
||||
levelNext++;
|
||||
|
||||
else if ((OnlySpaces && ch == '*' && chNext == '/'))
|
||||
levelNext--;
|
||||
|
||||
if (style == SCE_AHKL_NEUTRAL) {
|
||||
|
||||
if ((OnlySpaces && ch == '(') || ch == '{') {
|
||||
|
||||
// Measure the minimum before a '{' to allow
|
||||
// folding on "} else {"
|
||||
if (levelMinCurrent > levelNext)
|
||||
levelMinCurrent = levelNext;
|
||||
|
||||
levelNext++;
|
||||
|
||||
} else if ((OnlySpaces && ch == ')') || ch == '}') {
|
||||
|
||||
levelNext--;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!isspace(ch))
|
||||
visibleChars++;
|
||||
|
||||
if (atEOL || (i == endPos-1)) {
|
||||
|
||||
int levelUse = levelCurrent;
|
||||
int lev = levelUse | levelNext << 16;
|
||||
|
||||
if (levelUse < levelNext)
|
||||
lev |= SC_FOLDLEVELHEADERFLAG;
|
||||
|
||||
if (lev != styler.LevelAt(lineCurrent))
|
||||
styler.SetLevel(lineCurrent, lev);
|
||||
|
||||
lineCurrent++;
|
||||
lineStartNext = styler.LineStart(lineCurrent+1);
|
||||
levelCurrent = levelNext;
|
||||
levelMinCurrent = levelCurrent;
|
||||
|
||||
if (atEOL && (i == static_cast<unsigned int>(styler.Length()-1))) // There is an empty line at end of file so give it same level and empty
|
||||
styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG);
|
||||
|
||||
//visibleChars = 0;
|
||||
OnlySpaces = true;
|
||||
|
||||
}
|
||||
|
||||
if (!isspace(ch))
|
||||
OnlySpaces = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
LexerModule lmAHKL(SCLEX_AHKL, LexerAHKL::LexerFactoryAHKL, "ahk; ahkl", ahklWordLists);
|
||||
150
src/StyleLexers/styleLexAHKL.c
Normal file
150
src/StyleLexers/styleLexAHKL.c
Normal file
@ -0,0 +1,150 @@
|
||||
#include "StyleLexers.h"
|
||||
|
||||
|
||||
KEYWORDLIST KeyWords_AHKL = {
|
||||
// Directives
|
||||
"#allowsamelinecomments #clipboardtimeout #commentflag #errorstdout #escapechar #hotkeyinterval "
|
||||
"#hotkeymodifiertimeout #hotstring #if #iftimeout #ifwinactive #ifwinexist #include #includeagain "
|
||||
"#installkeybdhook #installmousehook #keyhistory #ltrim #maxhotkeysperinterval #maxmem #maxthreads "
|
||||
"#maxthreadsbuffer #maxthreadsperhotkey #menumaskkey #noenv #notrayicon #persistent #singleinstance "
|
||||
"#usehook #warn #winactivateforce",
|
||||
// Commands
|
||||
"autotrim blockinput clipwait control controlclick controlfocus controlget controlgetfocus "
|
||||
"controlgetpos controlgettext controlmove controlsend controlsendraw controlsettext coordmode "
|
||||
"critical detecthiddentext detecthiddenwindows drive driveget drivespacefree edit endrepeat envadd "
|
||||
"envdiv envget envmult envset envsub envupdate fileappend filecopy filecopydir filecreatedir "
|
||||
"filecreateshortcut filedelete filegetattrib filegetshortcut filegetsize filegettime filegetversion "
|
||||
"fileinstall filemove filemovedir fileread filereadline filerecycle filerecycleempty fileremovedir "
|
||||
"fileselectfile fileselectfolder filesetattrib filesettime formattime getkeystate groupactivate "
|
||||
"groupadd groupclose groupdeactivate gui guicontrol guicontrolget hideautoitwin hotkey if ifequal "
|
||||
"ifexist ifgreater ifgreaterorequal ifinstring ifless iflessorequal ifmsgbox ifnotequal ifnotexist "
|
||||
"ifnotinstring ifwinactive ifwinexist ifwinnotactive ifwinnotexist imagesearch inidelete iniread "
|
||||
"iniwrite input inputbox keyhistory keywait listhotkeys listlines listvars menu mouseclick "
|
||||
"mouseclickdrag mousegetpos mousemove msgbox outputdebug pixelgetcolor pixelsearch postmessage "
|
||||
"process progress random regdelete regread regwrite reload run runas runwait send sendevent "
|
||||
"sendinput sendmessage sendmode sendplay sendraw setbatchlines setcapslockstate setcontroldelay "
|
||||
"setdefaultmousespeed setenv setformat setkeydelay setmousedelay setnumlockstate setscrolllockstate "
|
||||
"setstorecapslockmode settitlematchmode setwindelay setworkingdir shutdown sort soundbeep soundget "
|
||||
"soundgetwavevolume soundplay soundset soundsetwavevolume splashimage splashtextoff splashtexton "
|
||||
"splitpath statusbargettext statusbarwait stringcasesense stringgetpos stringleft stringlen "
|
||||
"stringlower stringmid stringreplace stringright stringsplit stringtrimleft stringtrimright "
|
||||
"stringupper sysget thread tooltip transform traytip urldownloadtofile winactivate winactivatebottom "
|
||||
"winclose winget wingetactivestats wingetactivetitle wingetclass wingetpos wingettext wingettitle "
|
||||
"winhide winkill winmaximize winmenuselectitem winminimize winminimizeall winminimizeallundo winmove "
|
||||
"winrestore winset winsettitle winshow winwait winwaitactive winwaitclose winwaitnotactive "
|
||||
"fileencoding",
|
||||
// Command Parameters
|
||||
"ltrim rtrim join ahk_id ahk_pid ahk_class ahk_group processname minmax controllist statuscd "
|
||||
"filesystem setlabel alwaysontop mainwindow nomainwindow useerrorlevel altsubmit hscroll vscroll "
|
||||
"imagelist wantctrla wantf2 vis visfirst wantreturn backgroundtrans minimizebox maximizebox "
|
||||
"sysmenu toolwindow exstyle check3 checkedgray readonly notab lastfound lastfoundexist alttab "
|
||||
"shiftalttab alttabmenu alttabandmenu alttabmenudismiss controllisthwnd hwnd deref pow bitnot "
|
||||
"bitand bitor bitxor bitshiftleft bitshiftright sendandmouse mousemove mousemoveoff "
|
||||
"hkey_local_machine hkey_users hkey_current_user hkey_classes_root hkey_current_config hklm hku "
|
||||
"hkcu hkcr hkcc reg_sz reg_expand_sz reg_multi_sz reg_dword reg_qword reg_binary reg_link "
|
||||
"reg_resource_list reg_full_resource_descriptor caret reg_resource_requirements_list "
|
||||
"reg_dword_big_endian regex pixel mouse screen relative rgb low belownormal normal abovenormal "
|
||||
"high realtime between contains in is integer float number digit xdigit alpha upper lower alnum "
|
||||
"time date not or and topmost top bottom transparent transcolor redraw region id idlast count "
|
||||
"list capacity eject lock unlock label serial type status seconds minutes hours days read parse "
|
||||
"logoff close error single shutdown menu exit reload tray add rename check uncheck togglecheck "
|
||||
"enable disable toggleenable default nodefault standard nostandard color delete deleteall icon "
|
||||
"noicon tip click show edit progress hotkey text picture pic groupbox button checkbox radio "
|
||||
"dropdownlist ddl combobox statusbar treeview listbox listview datetime monthcal updown slider "
|
||||
"tab tab2 iconsmall tile report sortdesc nosort nosorthdr grid hdr autosize range xm ym ys xs xp "
|
||||
"yp font resize owner submit nohide minimize maximize restore noactivate na cancel destroy "
|
||||
"center margin owndialogs guiescape guiclose guisize guicontextmenu guidropfiles tabstop section "
|
||||
"wrap border top bottom buttons expand first lines number uppercase lowercase limit password "
|
||||
"multi group background bold italic strike underline norm theme caption delimiter flash style "
|
||||
"checked password hidden left right center section move focus hide choose choosestring text pos "
|
||||
"enabled disabled visible notimers interrupt priority waitclose unicode tocodepage fromcodepage "
|
||||
"yes no ok cancel abort retry ignore force on off all send wanttab monitorcount monitorprimary "
|
||||
"monitorname monitorworkarea pid base useunsetlocal useunsetglobal localsameasglobal str astr wstr "
|
||||
"int64 int short char uint64 uint ushort uchar float double int64p intp shortp charp uint64p uintp "
|
||||
"ushortp ucharp floatp doublep ptr",
|
||||
// Control Flow
|
||||
"break continue else exit exitapp gosub goto loop onexit pause repeat return settimer sleep "
|
||||
"suspend static global local byref while until for",
|
||||
// Built-in Functions
|
||||
"abs acos asc asin atan ceil chr cos dllcall exp fileexist floor getkeystate numget numput "
|
||||
"registercallback il_add il_create il_destroy instr islabel isfunc ln log lv_add lv_delete "
|
||||
"lv_deletecol lv_getcount lv_getnext lv_gettext lv_insert lv_insertcol lv_modify lv_modifycol "
|
||||
"lv_setimagelist mod onmessage round regexmatch regexreplace sb_seticon sb_setparts sb_settext "
|
||||
"sin sqrt strlen substr tan tv_add tv_delete tv_getchild tv_getcount tv_getnext tv_get tv_getparent "
|
||||
"tv_getprev tv_getselection tv_gettext tv_modify varsetcapacity winactive winexist trim ltrim rtrim "
|
||||
"fileopen strget strput object isobject objinsert objremove objminindex objmaxindex objsetcapacity "
|
||||
"objgetcapacity objgetaddress objnewenum objaddref objrelease objclone _insert _remove _minindex "
|
||||
"_maxindex _setcapacity _getcapacity _getaddress _newenum _addref _release _clone comobjcreate "
|
||||
"comobjget comobjconnect comobjerror comobjactive comobjenwrap comobjunwrap comobjparameter "
|
||||
"comobjmissing comobjtype comobjvalue comobjarray",
|
||||
// Built-in Variables
|
||||
"a_ahkpath a_ahkversion a_appdata a_appdatacommon a_autotrim a_batchlines a_caretx a_carety "
|
||||
"a_computername a_controldelay a_cursor a_dd a_ddd a_dddd a_defaultmousespeed a_desktop "
|
||||
"a_desktopcommon a_detecthiddentext a_detecthiddenwindows a_endchar a_eventinfo a_exitreason "
|
||||
"a_formatfloat a_formatinteger a_gui a_guievent a_guicontrol a_guicontrolevent a_guiheight "
|
||||
"a_guiwidth a_guix a_guiy a_hour a_iconfile a_iconhidden a_iconnumber a_icontip a_index a_ipaddress1 "
|
||||
"a_ipaddress2 a_ipaddress3 a_ipaddress4 a_isadmin a_iscompiled a_issuspended a_keydelay a_language "
|
||||
"a_lasterror a_linefile a_linenumber a_loopfield a_loopfileattrib a_loopfiledir a_loopfileext "
|
||||
"a_loopfilefullpath a_loopfilelongpath a_loopfilename a_loopfileshortname a_loopfileshortpath "
|
||||
"a_loopfilesize a_loopfilesizekb a_loopfilesizemb a_loopfiletimeaccessed a_loopfiletimecreated "
|
||||
"a_loopfiletimemodified a_loopreadline a_loopregkey a_loopregname a_loopregsubkey "
|
||||
"a_loopregtimemodified a_loopregtype a_mday a_min a_mm a_mmm a_mmmm a_mon a_mousedelay a_msec "
|
||||
"a_mydocuments a_now a_nowutc a_numbatchlines a_ostype a_osversion a_priorhotkey a_programfiles "
|
||||
"a_programs a_programscommon a_screenheight a_screenwidth a_scriptdir a_scriptfullpath a_scriptname "
|
||||
"a_sec a_space a_startmenu a_startmenucommon a_startup a_startupcommon a_stringcasesense a_tab a_temp "
|
||||
"a_thishotkey a_thismenu a_thismenuitem a_thismenuitempos a_tickcount a_timeidle a_timeidlephysical "
|
||||
"a_timesincepriorhotkey a_timesincethishotkey a_titlematchmode a_titlematchmodespeed a_username "
|
||||
"a_wday a_windelay a_windir a_workingdir a_yday a_year a_yweek a_yyyy clipboard clipboardall comspec "
|
||||
"programfiles a_thisfunc a_thislabel a_ispaused a_iscritical a_isunicode a_ptrsize errorlevel "
|
||||
"true false",
|
||||
// Keyboard & Mouse Keys
|
||||
"shift lshift rshift alt lalt ralt control lcontrol rcontrol ctrl lctrl rctrl lwin rwin appskey "
|
||||
"altdown altup shiftdown shiftup ctrldown ctrlup lwindown lwinup rwindown rwinup lbutton rbutton "
|
||||
"mbutton wheelup wheeldown xbutton1 xbutton2 joy1 joy2 joy3 joy4 joy5 joy6 joy7 joy8 joy9 joy10 joy11 "
|
||||
"joy12 joy13 joy14 joy15 joy16 joy17 joy18 joy19 joy20 joy21 joy22 joy23 joy24 joy25 joy26 joy27 "
|
||||
"joy28 joy29 joy30 joy31 joy32 joyx joyy joyz joyr joyu joyv joypov joyname joybuttons joyaxes "
|
||||
"joyinfo space tab enter escape esc backspace bs delete del insert ins pgup pgdn home end up down "
|
||||
"left right printscreen ctrlbreak pause scrolllock capslock numlock numpad0 numpad1 numpad2 numpad3 "
|
||||
"numpad4 numpad5 numpad6 numpad7 numpad8 numpad9 numpadmult numpadadd numpadsub numpaddiv numpaddot "
|
||||
"numpaddel numpadins numpadclear numpadup numpaddown numpadleft numpadright numpadhome numpadend "
|
||||
"numpadpgup numpadpgdn numpadenter f1 f2 f3 f4 f5 f6 f7 f8 f9 f10 f11 f12 f13 f14 f15 f16 f17 f18 f19 "
|
||||
"f20 f21 f22 f23 f24 browser_back browser_forward browser_refresh browser_stop browser_search "
|
||||
"browser_favorites browser_home volume_mute volume_down volume_up media_next media_prev media_stop "
|
||||
"media_play_pause launch_mail launch_media launch_app1 launch_app2 blind click raw wheelleft "
|
||||
"wheelright",
|
||||
// User Defined 1
|
||||
"",
|
||||
// User Defined 2
|
||||
"" };
|
||||
|
||||
|
||||
EDITLEXER lexAHKL = {
|
||||
SCLEX_AHKL, IDS_LEX_AHKL, L"AutoHotkey_L Script", L"ahkl; ahk; ia; scriptlet", L"",
|
||||
&KeyWords_AHKL, {
|
||||
{ STYLE_DEFAULT, IDS_LEX_STR_63126, L"Default", L"", L"" },
|
||||
//{ SCE_AHK_NEUTRAL, IDS_LEX_STR_63126, L"Default", L"", L"" },
|
||||
{ SCE_AHKL_IDENTIFIER, IDS_LEX_STR_63129, L"Identifier", L"", L"" },
|
||||
{ MULTI_STYLE(SCE_AHKL_COMMENTDOC,SCE_AHKL_COMMENTLINE,SCE_AHKL_COMMENTBLOCK,SCE_AHKL_COMMENTKEYWORD), IDS_LEX_STR_63127, L"Comment", L"fore:#008000", L"" },
|
||||
{ MULTI_STYLE(SCE_AHKL_STRING,SCE_AHKL_STRINGOPTS,SCE_AHKL_STRINGBLOCK,SCE_AHKL_STRINGCOMMENT), IDS_LEX_STR_63131, L"String", L"fore:#404040", L"" },
|
||||
{ SCE_AHKL_LABEL, IDS_LEX_STR_63235, L"Label", L"fore:#0000DD", L"" },
|
||||
{ SCE_AHKL_HOTKEY, IDS_LEX_STR_63349, L"HotKey", L"fore:#00AADD", L"" },
|
||||
{ SCE_AHKL_HOTSTRING, IDS_LEX_STR_63350, L"HotString", L"fore:#00BBBB", L"" },
|
||||
{ SCE_AHKL_HOTSTRINGOPT, IDS_LEX_STR_63351, L"KeyHotstringOption", L"fore:#990099", L"" },
|
||||
{ SCE_AHKL_HEXNUMBER, IDS_LEX_STR_63287, L"Hex Number", L"fore:#880088", L"" },
|
||||
{ SCE_AHKL_DECNUMBER, IDS_LEX_STR_63130, L"Number", L"fore:#FF9000", L"" },
|
||||
{ SCE_AHKL_VAR, IDS_LEX_STR_63249, L"Variable", L"fore:#FF9000", L"" },
|
||||
{ SCE_AHKL_VARREF, IDS_LEX_STR_63309, L"Variable Dereferencing", L"fore:#990055", L"" },
|
||||
{ SCE_AHKL_OBJECT, IDS_LEX_STR_63347, L"Object", L"fore:#008888", L"" },
|
||||
{ SCE_AHKL_USERFUNCTION, IDS_LEX_STR_63305, L"User-Defined Function", L"fore:#0000DD", L"" },
|
||||
{ SCE_AHKL_DIRECTIVE, IDS_LEX_STR_63203, L"Directive", L"fore:#4A0000; italic", L"" },
|
||||
{ SCE_AHKL_COMMAND, IDS_LEX_STR_63236, L"Command", L"fore:#0000DD; bold", L"" },
|
||||
{ SCE_AHKL_PARAM, IDS_LEX_STR_63281, L"Parameter", L"fore:#0085DD", L"" },
|
||||
{ SCE_AHKL_CONTROLFLOW, IDS_LEX_STR_63310, L"Flow of Control", L"fore:#0000DD;", L"" },
|
||||
{ SCE_AHKL_BUILTINFUNCTION, IDS_LEX_STR_63277, L"Function", L"fore:#DD00DD", L"" },
|
||||
{ SCE_AHKL_BUILTINVAR, IDS_LEX_STR_63312, L"Built-In Variables", L"fore:#EE3010; bold", L"" },
|
||||
{ SCE_AHKL_KEY, IDS_LEX_STR_63348, L"Key", L"fore:#A2A2A2", L"" },
|
||||
//{ SCE_AHKL_USERDEFINED1, IDS_LEX_STR_63106, L"User Defined", L"fore:#800020", L"" },
|
||||
//{ SCE_AHKL_USERDEFINED2, IDS_LEX_STR_63106, L"User Defined", L"fore:#800020", L"" },
|
||||
{ SCE_AHKL_ESCAPESEQ, IDS_LEX_STR_63306, L"Escape", L"fore:#660000; italic", L"" },
|
||||
{ SCE_AHKL_ERROR, IDS_LEX_STR_63261, L"Error", L"back:#FF0000", L"" },
|
||||
{ -1, 00000, L"", L"", L"" } } };
|
||||
Loading…
Reference in New Issue
Block a user