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'.
This commit is contained in:
Neil Hodgson 2025-04-05 14:30:44 +11:00
parent 78b80c0e53
commit 65b14241d6
4 changed files with 87 additions and 2 deletions

View File

@ -594,6 +594,18 @@
</tr>
</table>
<h2 id="Releases">Releases</h2>
<h3>
<a href="https://www.scintilla.org/lexilla545.zip">Release 5.4.5</a>
</h3>
<ul>
<li>
Released 2 April 2025.
</li>
<li>
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'.
</li>
</ul>
<h3>
<a href="https://www.scintilla.org/lexilla544.zip">Release 5.4.4</a>
</h3>

View File

@ -14,6 +14,7 @@
#include <string>
#include <string_view>
#include <map>
#include "ILexer.h"
#include "Scintilla.h"
@ -25,6 +26,7 @@
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"
#include "DefaultLexer.h"
using namespace Scintilla;
@ -32,10 +34,21 @@ using namespace Lexilla;
namespace {
// Options used for LexerMakeFile
struct OptionsMake {
};
const char *const makeWordListDescription[] = {
"Directives",
nullptr
};
struct OptionSetMake : public OptionSet<OptionsMake> {
OptionSetMake() {
DefineWordListSets(makeWordListDescription);
}
};
const LexicalClass lexicalClasses[] = {
// Lexer makefile SCLEX_MAKEFILE SCE_MAKE_
0, "SCE_MAKE_DEFAULT", "default", "White space",
@ -53,11 +66,35 @@ bool AtEOL(Accessor &styler, Sci_PositionU i) {
}
class LexerMakeFile : public DefaultLexer {
WordList directives;
OptionsMake options;
OptionSetMake osMake;
public:
LexerMakeFile() :
DefaultLexer("makefile", SCLEX_MAKEFILE, lexicalClasses, std::size(lexicalClasses)) {
}
const char *SCI_METHOD PropertyNames() override {
return osMake.PropertyNames();
}
int SCI_METHOD PropertyType(const char *name) override {
return osMake.PropertyType(name);
}
const char *SCI_METHOD DescribeProperty(const char *name) override {
return osMake.DescribeProperty(name);
}
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
const char *SCI_METHOD PropertyGet(const char *key) override {
return osMake.PropertyGet(key);
}
const char *SCI_METHOD DescribeWordListSets() override {
return osMake.DescribeWordListSets();
}
Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override;
void ColouriseMakeLine(std::string_view lineBuffer,
Sci_PositionU startLine, Sci_PositionU endPos, Accessor &styler);
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override;
static ILexer5 *LexerFactoryMakeFile() {
@ -65,7 +102,30 @@ public:
}
};
void ColouriseMakeLine(
Sci_Position SCI_METHOD LexerMakeFile::PropertySet(const char *key, const char *val) {
if (osMake.PropertySet(&options, key, val)) {
return 0;
}
return -1;
}
Sci_Position SCI_METHOD LexerMakeFile::WordListSet(int n, const char *wl) {
WordList *wordListN = nullptr;
switch (n) {
case 0:
wordListN = &directives;
break;
default:
break;
}
Sci_Position firstModification = -1;
if (wordListN && wordListN->Set(wl)) {
firstModification = 0;
}
return firstModification;
}
void LexerMakeFile::ColouriseMakeLine(
const std::string_view lineBuffer,
Sci_PositionU startLine,
Sci_PositionU endPos,
@ -93,6 +153,18 @@ void ColouriseMakeLine(
styler.ColourTo(endPos, SCE_MAKE_PREPROCESSOR);
return;
}
if (IsUpperOrLowerCase(lineBuffer[i]) &&
(lineBuffer.find_first_of(":=") == std::string::npos)) {
const std::string_view firstWord(lineBuffer.substr(i));
size_t endWord = 0;
while ((endWord < firstWord.length()) && IsUpperOrLowerCase(firstWord[endWord])) {
endWord++;
}
if (directives.InList(firstWord.substr(0, endWord))) {
styler.ColourTo(startLine + i + endWord - 1, SCE_MAKE_PREPROCESSOR);
i += endWord;
}
}
}
int varCount = 0;
while (i < lengthLine) {

View File

@ -1 +1,2 @@
lexer.*.mak=makefile
keywords.*.mak=ifdef

View File

@ -11,7 +11,7 @@
{2}!IFDEF DEBUG
{0}
{1}# 'ifdef DEBUG' GNI make directive default=0
{0}ifdef DEBUG
{2}ifdef{0} DEBUG
{1}# '$(' ID EOL=9
{3}X{4}={9}$(