import scintillua/scintillua
In order to install Scintillua for one user (e.g. yourself) without administrator privileges:
Unpack Scintillua to a location of your choosing.
Add the following to the end of your SciTEUser.properties on Windows or
.SciTEUser.properties on Linux:
import /path/to/scintillua/scintillua
lexilla.context.scintillua.lexers=/path/to/scintillua/lexers
where /path/to/scintillua/lexers
is the full path of Scintillua’s lexers/ directory from
step 1.
With Scintillua installed, SciTE will use Scintillua’s Lua lexers whenever possible (as indicated
in scintillua.properties). If a Lua lexer is loaded but you prefer to use a different
one, add to your SciTEUser.properties (Windows) or .SciTEUser.properties (Linux) file:
lexer.$(file.patterns.name)=scintillua.name
where name
is the name of the Scintillua lexer you prefer. (Note that Scintillua lexers have
a “scintillua.” prefix when used with SciTE.) If you prefer to use SciTE’s lexer instead of
Scintillua’s, simply remove from scintillua.properties the lines:
file.patterns.name=...
lexer.$(file.patterns.name)=scintillua.name
keywords.$(file.patterns.name)=scintillua
keywords2.$(file.patterns.name)=scintillua
keywords9.$(file.patterns.name)=scintillua
(You could manually override Scintillua’s file.patterns.name
, lexer
, and keywords
settings
from your SciTE user properties file, but it’s easier to just change scintillua.properties.)
Scintillua’s Lua lexers also have their own keyword sets, which are distinct from SciTE lexer
keyword sets. If you would like to change the set of keywords that a Scintillua lexer uses,
add to your SciTEUser.properties (Windows) or .SciTEUser.properties (Linux) file:
keywords.$(file.patterns.name)=set of keywords
keywords2.$(filepatterns.name)=another set of keywords
with the desired set(s) of keywords in the same order as the Scintillua lexers/name
.lua
lexer’s calls to lex:set_word_list()
. For example, the Lua lexer’s first set of keywords is for
reserved words, the second is for built-in global functions, the third is for library functions,
the fourth is for built-in global constants, and the fifth is for library constants.
Scintillua comes with a set of universal color themes in its themes/ directory. By default, the
‘scite’ theme is used, which is similar to SciTE’s default color theme. You can use a different
theme by importing it in a properties file. For example:
import /path/to/scintillua/themes/light
Scintillua’s lexers support the following properties which can also be set from a properties file:
fold.scintillua.by.indentation
: Whether or not to fold based on indentation level if a lexer does not
have a folder. Some lexers automatically enable this option. It is disabled by default.
fold.scintillua.on.zero.sum.lines
: Whether or not to mark as a fold point lines that contain both an
ending and starting fold point. For example, } else {
would be marked as a fold point. This
option is disabled by default.
fold.scintillua.compact
: Whether or not to include in a fold any subsequent blank lines. It
is disabled by default.
If you get incorrect or no syntax highlighting, check the following:
Does the language in question have a Lua lexer in Scintillua’s lexers/ directory? If not,
you will have to write one.
Does Scintillua’s scintillua.properties have your language’s file extension defined? If not,
add it to the file.patterns.
name
property.
Does the file extension recognized in Scintillua’s scintillua.properties correspond to the
language in question? If not, add or re-assign it to the appropriate Lua lexer. Do not forget
the “scintillua.” prefix for lexers.
Feel free to contribute new lexers, as well as submit corrections, updates, or additions
to file types.
Note: any Scintilla lexer-specific features in SciTE will not work in Scintillua’s lexers.
These include, but are not limited to:
Style, keyword, and folding properties in *.properties files.
Python colon matching.
HTML/XML tag auto-completion.
Using Scintillua with Other Apps
In order to drop Scintillua into any other existing installation of a Scintilla-based application
that supports the Lexilla protocol, that application must allow you to:
Specify the location of, and/or load Scintillua’s Scintillua.dll (Windows) or
libscintillua.so (Linux) library.
Specify the path to Scintillua’s lexers/ directory via an internal call to the Lexilla
protocol’s SetLibraryProperty()
function using the “scintillua.lexers” key.
Load a lexer using the Lexilla protocol’s CreateLexer()
function, passing in the name of
a Lua lexer to load (without the .lua extension).
Give the resulting ILexer5*
pointer to Scintilla, e.g. via Scintilla’s SCI_SETILEXER
message.
Optionally handle errors when the returned pointer is null by calling Scintillua’s
GetCreateLexerError()
function to see what went wrong.
Optionally set keyword lists via Scintilla’s SCI_SETKEYWORDS message with the help of
SCI_DESCRIBEKEYWORDSETS. Scintillua’s lexers have built-in word lists, but they can
be overridden.
The Scintillua lexer largely behaves like a normal Scintilla lexer. However, unlike most
other lexers Scintillua does not have static style numbers, which makes styling a bit more
complicated. Your application must call the lexer’s NamedStyles()
function (defined by the
ILexer5
interface), which returns the number of currently defined styles. (Note that the
returned number includes Scintilla’s 8 predefined styles.) It must then iterate over those style
numbers, calling NameOfStyle()
, in order to obtain a map of style names to numbers. With
that information, your application can then specify style settings for style numbers. Here’s
an example of how SciTE does it:
// Scintillua's style numbers are not constant, so ask it for names of styles and create a
// mapping of style numbers to more constant style definitions.
// For example, if Scintillua reports for the cpp lexer that style number 2 is a 'comment',
// create the property:
// style.scintillua.cpp.2=$(scintillua.styles.comment)
// That way the user can define 'scintillua.styles.comment' once and it will be used for whatever
// the style number for comments is in any given lexer.
// Similarly, if Scintillua reports for the lua lexer that style number 20 is 'string.longstring',
// create the property:
// style.scintillua.lua.20=$(scintillua.styles.string),$(scintillua.styles.string.longstring)
void SetScintilluaStyles(GUI::ScintillaWindow &wEditor, PropSetFile& props, const char *languageName) {
const auto setStyle = [&wEditor, &props, &languageName](int style) {
std::string finalPropStr;
const std::string &name = wEditor.NameOfStyle(style);
size_t end = std::string::npos;
end = name.find('.', ++end);
char propStr[128] = "";
sprintf(propStr, "$(scintillua.styles.%s),", end == std::string::npos ?
name.c_str() : name.substr(0, end).c_str());
finalPropStr += propStr;
} while (end != std::string::npos);
char key[256] = "";
sprintf(key, "style.%s.%0d", languageName, style);
props.Set(key, finalPropStr.c_str());
const int namedStyles = wEditor.NamedStyles(); // this count includes predefined styles
constexpr int LastPredefined = static_cast<int>(Scintilla::StylesCommon::LastPredefined);
constexpr int numPredefined = LastPredefined - StyleDefault + 1;
for (int i = 0; i < std::min(namedStyles - numPredefined, StyleDefault); i++) {
setStyle(i);
for (int i = StyleDefault; i <= LastPredefined; i++) {
setStyle(i);
for (int i = LastPredefined + 1; i < namedStyles; i++) {
setStyle(i);
In addition to not having static style numbers, Scintillua does not have static keyword lists
should you wish to override the a given lexer’s built-in list(s). Your application can call the
lexer’s DescribeWordListSets()
function (defined by the ILexer5
interface), which returns
a list of keyword set identifier names. For the first set, call the lexer’s WordListSet()
function with an index of 0
and a list of overriding words. For the second, use 1
, and so on.
Scintillua’s lexers support the following properties:
fold
: Whether or not folding is enabled for the lexers that support it. This option is
disabled by default. Set to 1
to enable.
fold.scintillua.by.indentation
: Whether or not to fold based on indentation level if a
lexer does not have a folder. Some lexers automatically enable this option. It is disabled
by default. Set to 1
to enable.
fold.scintillua.on.zero.sum.lines
: Whether or not to mark as a fold point lines that contain
both an ending and starting fold point. For example, } else {
would be marked as a fold
point. This option is disabled by default. Set to 1
to enable.
fold.scintillua.compact
: Whether or not blank lines after an ending fold point are included
in that fold. This option is disabled by default. Set to 1
to enable.
Lexer Detection
Applications can leverage Scintillua’s internal database of lexer names associated with filenames
and extensions, and lexer names associated with content lines like shebang lines. In order to do this:
Initially call CreateLexer("text")
and then set it using Scintilla’s SCI_SETILEXER
message.
Set the lexer.scintillua.filename
and/or lexer.scintillua.line
properties to set the
filename and/or content line, respectively, used for detecting a lexer. You may wish to
truncate the content line in order to avoid the overhead of dealing with a very long line,
such as minified JavaScript. The first 128 bytes seems reasonable.
Use Scintilla’s SCI_PRIVATELEXERCALL message along with the operation SCLUA_DETECT
(1) to store the detected lexer’s name in the given pointer
argument. This operation
behaves like other Scintilla string API functions: when passing a null pointer argument,
the length of the string that should be allocated is returned.
If the result is a non-empty string, call CreateLexer()
with that result and set the newly
created lexer using SCI_SETILEXER.
Error Handling
Scintillua reports errors in one of two ways:
If the CreateLexer()
call fails and returns a null pointer, you can retrieve the error
message using Scintillua’s GetCreateLexerError()
. This can happen when the “scintillua.lexers”
property is not correctly set or when there is an error loading a particular Lua lexer.
If there is an error during a lex or fold operation, the error message is stored in the
“lexer.scintillua.error” property. This property only contains the most recent error (if any).
Critical errors are also printed to stderr.
Compiling Scintillua Directly into an App
You can compile Scintillua directly (statically) into your Scintilla-based application by:
Adding Scintillua.h and Scintillua.cxx to your project’s sources.
Downloading and adding Lua and LPeg to your project’s sources. Scintillua supports
Lua 5.3+.
Adding infrastructure to build Lua, LPeg, Scintillua.cxx, and linking them all into your
application.
Here is a sample portion of a Makefile with Lua 5.3 as an example:
# ...
sci_flags = [flags used to compile Scintilla and Lexilla]
scintillua_obj = Scintillua.o
lua_flags = -Iscintillua/lua/src
lua_objs = lapi.o lcode.o lctype.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \
lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o lundump.o lvm.o lzio.o \
lauxlib.o lbaselib.o lmathlib.o lstrlib.o ltablib.o lutf8lib.o \
lpcap.o lpcode.o lpprint.o lptree.o lpvm.o
$(scintillua_obj): scintillua/Scintillua.cxx
g++ $(sci_flags) $(lua_flags) -c $< -o $@
$(lua_objs): scintillua/lua/src/*.c scintillua/lua/src/lib/*.c
gcc $(lua_flags) -c $^
# ...
[your app]: [your dependencies] $(scintillua_obj) $(lua_objs)
Windows note: when cross-compiling for Windows statically, you will need to pass -DNO_DLL
to the compiler when compiling Scintillua.cxx.
In order to use Scintillua’s lexers in your application:
Call Scintillua’s SetLibraryProperty()
with “scintillua.lexers” as the key and the path to
Scintillua’s lexers/ directory as the value.
Call Scintillua’s CreateLexer()
with the name of a Lua lexer (without the .lua extension)
to load.
Call Scintilla’s SCI_SETILEXER message, passing the lexer returned in step 2.
Optionally handle errors when the returned pointer is null by calling Scintillua’s
GetCreateLexerError()
to see what went wrong.
For example, using the GTK platform:
GtkWidget *sci = scintilla_new();
SetLibraryProperty("scintillua.lexers", "/path/to/lexers/");
ILEXER5* lua_lexer = CreateLexer("lua");
if (lua_lexer)
send_scintilla_message(SCINTILLA(sci), SCI_SETILEXER, 0, (sptr_t)lua_lexer);
fprintf("error creating lexer: %s\n", GetCreateLexerError());
Your application will then have to query Scintillua for how many styles are currently defined
and what the names of those styles are in order to create a map of style names to style numbers
for specifying style settings. The previous section has
an example of this process.
Error Handling
Scintillua reports errors in one of two ways:
If the CreateLexer()
call fails and returns a null pointer, you can retrieve the error
message using Scintillua’s GetCreateLexerError()
. This can happen when the “scintillua.lexers”
property is not correctly set or when there is an error loading a particular Lua lexer.
If there is an error during a lex or fold operation, the error message is stored in the
“lexer.scintillua.error” property. This property only contains the most recent error (if any).
Critical errors are also printed to stderr.
Using Scintillua as a Lua Library
In order to use Scintillua as a Lua library, simply place the lexers/ directory in your Lua
path (or modify Lua’s package.path
accordingly), require()
the lexer
library, load()
a lexer, and call that lexer’s lex()
function. Here is an example interactive Lua session
doing this:
$> lua
> lexer_path = '/home/mitchell/code/scintillua/lexers/?.lua'
> package.path = package.path .. ';' .. lexer_path
> c = require('lexer').load('ansi_c')
> tokens = c:lex('int main() { return 0; }')
> for i = 1, #tokens, 2 do print(tokens[i], tokens[i+1]) end
type 4
whitespace.ansi_c 5
function 9
operator 10
operator 11
whitespace.ansi_c 12
operator 13
whitespace.ansi_c 14
keyword 20
whitespace.ansi_c 21
number 22
operator 23
whitespace.ansi_c 24
operator 25
If you are unsure of which lexer to use for a given filename and/or content line (e.g. shebang line), you can
call detect()
and pass the result to load()
if it is non-nil.