ScintillaOrg / lexilla

A library of language lexers for use with Scintilla
https://www.scintilla.org/Lexilla.html
Other
175 stars 63 forks source link

Scintillua issue with Lexilla::MakeLexer #30

Open ittegrat opened 2 years ago

ittegrat commented 2 years ago

With Scintillua installed in SciTE (Sc1, single file), I can't disable a Lua lexer resetting the property lexer.$(file.patterns.name)=name to the original lexilla lexer. It seems to me that a recent commit in lexilla (ScintillaOrg/lexilla@e4817a1) breaks the Scintillua behavior and a default Lua lexer is always created and set after been called by Lexilla::MakeLexer (see orbitalquark/scintillua#54).

As far as I understand, the attempt made here to match the lexer name without the namespace is due to the fact that the GetNameSpace function is optional. I would propose to modify the test if (lexLib.fnCL) { adding a check that the namespace is empty if (lexLib.fnCL && lexLib.nameSpace.empty()) {, so the attempt is made only if the implementation does not provide the GetNameSpace function. Is it sensible ?

nyamatongwe commented 2 years ago

Namespaces are supposed to be optional - you don't have to specify them if you are willing to receive a lexer with that name from any library. If you specifically want the Lua lexer can't you ask for lexer.$(file.patterns.name)=lpeg.name?

nyamatongwe commented 2 years ago

Which library is not providing a namespace? Lexilla as installed into SciTE should be using "lexilla" and Scintillua should be using "lpeg".

ittegrat commented 2 years ago

My use case is the following: I would use the Lua lexer for a private DSL language and the standard Lexilla lexers for all the other files. I encounter the problem using Sc1. As far as I understand, the problem doesn't occur in SciTE because the lexilla.dll is probed before the LexLPeg.dll. A minimal set of properties to reproduce the problem is the following:

SciTEGlobal.properties

import lexers/lpeg

lexers/lpeg.properties

lexilla.context.lpeg.home=$(SciteDefaultHome)/lexers
lexilla.context.lpeg.color.theme=scite
if PLAT_WIN
  lexilla.path=.;$(lexilla.context.lpeg.home)/LexLPeg.dll
if PLAT_GTK
  lexilla.path=.;$(lexilla.context.lpeg.home)/liblexlpeg.so
fold.by.indentation=0
fold.line.groups=0
fold.on.zero.sum.lines=0

With these settings, I would expect a file, e.g. a python file, to be styled with the static Lexilla lexer set in the embedded properties, but instead, it is styled with a default lpeg lexer. I tried to to set the namespace, i.e. lexer.$(file.patterns.py)=lexilla.python, but is is not recognized. Does the static lexilla library define the namespace?.

nyamatongwe commented 2 years ago

The statically linked lexers are checked after the dynamically loaded lexers and don't have a namespace. You could grab a copy of Lexilla.dll from a full SciTE download and refer to it in lexilla.path.

There could be a second try of the static call inserting "lexilla." before the name.

nyamatongwe commented 2 years ago

This patch implements a static namespace that refers to statically linked lexers with statements like lexer.*.cpp=static.cpp. That then requires the static. name in other properties style.static.cpp.4=$(colour.number).

diff --git a/access/LexillaAccess.cxx b/access/LexillaAccess.cxx
index f612ce29..2a4b6450 100644
--- a/access/LexillaAccess.cxx
+++ b/access/LexillaAccess.cxx
@@ -234,6 +234,10 @@ Scintilla::ILexer5 *Lexilla::MakeLexer(std::string_view languageName) {
            }
        }
    }
+   constexpr std::string_view builtin("static.");
+   if (HasPrefix(sLanguageName, builtin) && pCreateLexerDefault) {
+       return pCreateLexerDefault(sLanguageName.substr(builtin.size()).c_str());
+   }
    // If no match with namespace, try to just match name
    for (const LexLibrary &lexLib : libraries) {
        if (lexLib.fnCL) {

The static namespace is probed after the dynamically loaded lexer's namespaces but before checking for names without namespaces.