Update scintilla to 3.21.1

This commit is contained in:
Maarten Bent 2020-07-28 22:57:04 +02:00
parent 0a33da8058
commit 6c3b0f66f3
No known key found for this signature in database
GPG key ID: 58AAEE3F4A4FD070
223 changed files with 21171 additions and 9779 deletions

View file

@ -2,19 +2,19 @@ License for Scintilla and SciTE
Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
All Rights Reserved
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation.
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation.
NEIL HODGSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS, IN NO EVENT SHALL NEIL HODGSON BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
OR PERFORMANCE OF THIS SOFTWARE.
NEIL HODGSON DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS, IN NO EVENT SHALL NEIL HODGSON BE LIABLE FOR ANY
SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
OR PERFORMANCE OF THIS SOFTWARE.

View file

@ -0,0 +1,70 @@
// c++11 compatibility with some c++14 features and higher.
// This helps minimize changes from the default branch.
#ifndef COMPAT_H
#define COMPAT_H
#ifdef __cplusplus
#include <cmath>
#include <cstddef>
#include <memory>
#include <type_traits>
#include <utility>
namespace Sci {
// std::clamp
template <typename T>
inline constexpr T clamp(T val, T minVal, T maxVal) {
return (val > maxVal) ? maxVal : ((val < minVal) ? minVal : val);
}
// std::round (not present on older MacOSX SDKs)
template<class T>
T round(T arg) {
return ::round(arg);
}
// std::lround (not present on older MacOSX SDKs)
template<class T>
long lround(T arg) {
return ::lround(arg);
}
// std::make_unique
template<class T> struct _Unique_if {
typedef std::unique_ptr<T> _Single_object;
};
template<class T> struct _Unique_if<T[]> {
typedef std::unique_ptr<T[]> _Unknown_bound;
};
template<class T, size_t N> struct _Unique_if<T[N]> {
typedef void _Known_bound;
};
template<class T, class... Args>
typename _Unique_if<T>::_Single_object
make_unique(Args&&... args) {
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
template<class T>
typename _Unique_if<T>::_Unknown_bound
make_unique(size_t n) {
typedef typename std::remove_extent<T>::type U;
return std::unique_ptr<T>(new U[n]());
}
template<class T, class... Args>
typename _Unique_if<T>::_Known_bound
make_unique(Args&&...) = delete;
// std::size
template <typename T, size_t N>
constexpr size_t size(const T (&)[N]) noexcept {
return N;
}
}
#endif
#endif

View file

@ -10,15 +10,7 @@
#include "Sci_Position.h"
#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif
#ifdef _WIN32
#define SCI_METHOD __stdcall
#else
#define SCI_METHOD
#endif
enum { dvOriginal=0, dvLineEnd=1 };
@ -54,7 +46,7 @@ public:
virtual int SCI_METHOD GetCharacterAndWidth(Sci_Position position, Sci_Position *pWidth) const = 0;
};
enum { lvOriginal=0, lvSubStyles=1 };
enum { lvOriginal=0, lvSubStyles=1, lvMetaData=2, lvIdentity=3 };
class ILexer {
public:
@ -85,16 +77,21 @@ public:
virtual const char * SCI_METHOD GetSubStyleBases() = 0;
};
class ILoader {
class ILexerWithMetaData : public ILexerWithSubStyles {
public:
virtual int SCI_METHOD Release() = 0;
// Returns a status code from SC_STATUS_*
virtual int SCI_METHOD AddData(char *data, Sci_Position length) = 0;
virtual void * SCI_METHOD ConvertToDocument() = 0;
virtual int SCI_METHOD NamedStyles() = 0;
virtual const char * SCI_METHOD NameOfStyle(int style) = 0;
virtual const char * SCI_METHOD TagsOfStyle(int style) = 0;
virtual const char * SCI_METHOD DescriptionOfStyle(int style) = 0;
};
class ILexerWithIdentity : public ILexerWithMetaData {
public:
virtual const char * SCI_METHOD GetName() = 0;
virtual int SCI_METHOD GetIdentifier() = 0;
virtual const char * SCI_METHOD PropertyGet(const char *key) = 0;
};
#ifdef SCI_NAMESPACE
}
#endif
#endif

View file

@ -0,0 +1,21 @@
// Scintilla source code edit control
/** @file ILoader.h
** Interface for loading into a Scintilla document from a background thread.
**/
// Copyright 1998-2017 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#ifndef ILOADER_H
#define ILOADER_H
#include "Sci_Position.h"
class ILoader {
public:
virtual int SCI_METHOD Release() = 0;
// Returns a status code from SC_STATUS_*
virtual int SCI_METHOD AddData(const char *data, Sci_Position length) = 0;
virtual void * SCI_METHOD ConvertToDocument() = 0;
};
#endif

View file

@ -25,6 +25,7 @@
#define PLAT_FOX 0
#define PLAT_CURSES 0
#define PLAT_TK 0
#define PLAT_HAIKU 0
#if defined(FOX)
#undef PLAT_FOX
@ -38,6 +39,10 @@
#undef PLAT_CURSES
#define PLAT_CURSES 1
#elif defined(__HAIKU__)
#undef PLAT_HAIKU
#define PLAT_HAIKU 1
#elif defined(SCINTILLA_QT)
#undef PLAT_QT
#define PLAT_QT 1
@ -71,15 +76,10 @@
#endif
#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif
typedef float XYPOSITION;
typedef double XYACCUMULATOR;
inline int RoundXYPosition(XYPOSITION xyPos) {
return int(xyPos + 0.5);
}
// Underlying the implementation of the platform classes are platform specific types.
// Sometimes these need to be passed around by client code so they are defined here
@ -101,21 +101,31 @@ public:
XYPOSITION x;
XYPOSITION y;
explicit Point(XYPOSITION x_=0, XYPOSITION y_=0) : x(x_), y(y_) {
constexpr explicit Point(XYPOSITION x_=0, XYPOSITION y_=0) noexcept : x(x_), y(y_) {
}
static Point FromInts(int x_, int y_) {
static constexpr Point FromInts(int x_, int y_) noexcept {
return Point(static_cast<XYPOSITION>(x_), static_cast<XYPOSITION>(y_));
}
// Other automatically defined methods (assignment, copy constructor, destructor) are fine
constexpr bool operator!=(Point other) const noexcept {
return (x != other.x) || (y != other.y);
}
static Point FromLong(long lpoint);
constexpr Point operator+(Point other) const noexcept {
return Point(x + other.x, y + other.y);
}
constexpr Point operator-(Point other) const noexcept {
return Point(x - other.x, y - other.y);
}
// Other automatically defined methods (assignment, copy constructor, destructor) are fine
};
/**
* A geometric rectangle class.
* PRectangle is similar to the Win32 RECT.
* PRectangle is similar to Win32 RECT.
* PRectangles contain their top and left sides, but not their right and bottom sides.
*/
class PRectangle {
@ -125,113 +135,147 @@ public:
XYPOSITION right;
XYPOSITION bottom;
explicit PRectangle(XYPOSITION left_=0, XYPOSITION top_=0, XYPOSITION right_=0, XYPOSITION bottom_ = 0) :
constexpr explicit PRectangle(XYPOSITION left_=0, XYPOSITION top_=0, XYPOSITION right_=0, XYPOSITION bottom_ = 0) noexcept :
left(left_), top(top_), right(right_), bottom(bottom_) {
}
static PRectangle FromInts(int left_, int top_, int right_, int bottom_) {
static constexpr PRectangle FromInts(int left_, int top_, int right_, int bottom_) noexcept {
return PRectangle(static_cast<XYPOSITION>(left_), static_cast<XYPOSITION>(top_),
static_cast<XYPOSITION>(right_), static_cast<XYPOSITION>(bottom_));
}
// Other automatically defined methods (assignment, copy constructor, destructor) are fine
bool operator==(PRectangle &rc) const {
constexpr bool operator==(const PRectangle &rc) const noexcept {
return (rc.left == left) && (rc.right == right) &&
(rc.top == top) && (rc.bottom == bottom);
}
bool Contains(Point pt) const {
constexpr bool Contains(Point pt) const noexcept {
return (pt.x >= left) && (pt.x <= right) &&
(pt.y >= top) && (pt.y <= bottom);
}
bool ContainsWholePixel(Point pt) const {
constexpr bool ContainsWholePixel(Point pt) const noexcept {
// Does the rectangle contain all of the pixel to left/below the point
return (pt.x >= left) && ((pt.x+1) <= right) &&
(pt.y >= top) && ((pt.y+1) <= bottom);
}
bool Contains(PRectangle rc) const {
constexpr bool Contains(PRectangle rc) const noexcept {
return (rc.left >= left) && (rc.right <= right) &&
(rc.top >= top) && (rc.bottom <= bottom);
}
bool Intersects(PRectangle other) const {
constexpr bool Intersects(PRectangle other) const noexcept {
return (right > other.left) && (left < other.right) &&
(bottom > other.top) && (top < other.bottom);
}
void Move(XYPOSITION xDelta, XYPOSITION yDelta) {
void Move(XYPOSITION xDelta, XYPOSITION yDelta) noexcept {
left += xDelta;
top += yDelta;
right += xDelta;
bottom += yDelta;
}
XYPOSITION Width() const { return right - left; }
XYPOSITION Height() const { return bottom - top; }
bool Empty() const {
constexpr XYPOSITION Width() const noexcept { return right - left; }
constexpr XYPOSITION Height() const noexcept { return bottom - top; }
constexpr bool Empty() const noexcept {
return (Height() <= 0) || (Width() <= 0);
}
};
/**
* Holds a desired RGB colour.
* Holds an RGB colour with 8 bits for each component.
*/
constexpr const float componentMaximum = 255.0f;
class ColourDesired {
long co;
int co;
public:
ColourDesired(long lcol=0) {
co = lcol;
constexpr explicit ColourDesired(int co_=0) noexcept : co(co_) {
}
ColourDesired(unsigned int red, unsigned int green, unsigned int blue) {
Set(red, green, blue);
constexpr ColourDesired(unsigned int red, unsigned int green, unsigned int blue) noexcept :
co(red | (green << 8) | (blue << 16)) {
}
bool operator==(const ColourDesired &other) const {
constexpr bool operator==(const ColourDesired &other) const noexcept {
return co == other.co;
}
void Set(long lcol) {
co = lcol;
}
void Set(unsigned int red, unsigned int green, unsigned int blue) {
co = red | (green << 8) | (blue << 16);
}
static inline unsigned int ValueOfHex(const char ch) {
if (ch >= '0' && ch <= '9')
return ch - '0';
else if (ch >= 'A' && ch <= 'F')
return ch - 'A' + 10;
else if (ch >= 'a' && ch <= 'f')
return ch - 'a' + 10;
else
return 0;
}
void Set(const char *val) {
if (*val == '#') {
val++;
}
unsigned int r = ValueOfHex(val[0]) * 16 + ValueOfHex(val[1]);
unsigned int g = ValueOfHex(val[2]) * 16 + ValueOfHex(val[3]);
unsigned int b = ValueOfHex(val[4]) * 16 + ValueOfHex(val[5]);
Set(r, g, b);
}
long AsLong() const {
constexpr int AsInteger() const noexcept {
return co;
}
unsigned int GetRed() const {
// Red, green and blue values as bytes 0..255
constexpr unsigned char GetRed() const noexcept {
return co & 0xff;
}
unsigned int GetGreen() const {
constexpr unsigned char GetGreen() const noexcept {
return (co >> 8) & 0xff;
}
unsigned int GetBlue() const {
constexpr unsigned char GetBlue() const noexcept {
return (co >> 16) & 0xff;
}
// Red, green and blue values as float 0..1.0
constexpr float GetRedComponent() const noexcept {
return GetRed() / componentMaximum;
}
constexpr float GetGreenComponent() const noexcept {
return GetGreen() / componentMaximum;
}
constexpr float GetBlueComponent() const noexcept {
return GetBlue() / componentMaximum;
}
};
/**
* Holds an RGBA colour.
*/
class ColourAlpha : public ColourDesired {
public:
constexpr explicit ColourAlpha(int co_ = 0) noexcept : ColourDesired(co_) {
}
constexpr ColourAlpha(unsigned int red, unsigned int green, unsigned int blue) noexcept :
ColourDesired(red | (green << 8) | (blue << 16)) {
}
constexpr ColourAlpha(unsigned int red, unsigned int green, unsigned int blue, unsigned int alpha) noexcept :
ColourDesired(red | (green << 8) | (blue << 16) | (alpha << 24)) {
}
constexpr ColourAlpha(ColourDesired cd, unsigned int alpha) noexcept :
ColourDesired(cd.AsInteger() | (alpha << 24)) {
}
constexpr ColourDesired GetColour() const noexcept {
return ColourDesired(AsInteger() & 0xffffff);
}
constexpr unsigned char GetAlpha() const noexcept {
return (AsInteger() >> 24) & 0xff;
}
constexpr float GetAlphaComponent() const noexcept {
return GetAlpha() / componentMaximum;
}
ColourAlpha MixedWith(ColourAlpha other) const noexcept {
const unsigned int red = (GetRed() + other.GetRed()) / 2;
const unsigned int green = (GetGreen() + other.GetGreen()) / 2;
const unsigned int blue = (GetBlue() + other.GetBlue()) / 2;
const unsigned int alpha = (GetAlpha() + other.GetAlpha()) / 2;
return ColourAlpha(red, green, blue, alpha);
}
};
/**
* Holds an element of a gradient with an RGBA colour and a relative position.
*/
class ColourStop {
public:
float position;
ColourAlpha colour;
ColourStop(float position_, ColourAlpha colour_) noexcept :
position(position_), colour(colour_) {
}
};
/**
@ -254,7 +298,7 @@ struct FontParameters {
bool italic_=false,
int extraFontFlag_=0,
int technology_=0,
int characterSet_=0) :
int characterSet_=0) noexcept :
faceName(faceName_),
size(size_),
@ -271,19 +315,21 @@ struct FontParameters {
class Font {
protected:
FontID fid;
// Private so Font objects can not be copied
Font(const Font &);
Font &operator=(const Font &);
public:
Font();
Font() noexcept;
// Deleted so Font objects can not be copied
Font(const Font &) = delete;
Font(Font &&) = delete;
Font &operator=(const Font &) = delete;
Font &operator=(Font &&) = delete;
virtual ~Font();
virtual void Create(const FontParameters &fp);
virtual void Release();
FontID GetID() { return fid; }
FontID GetID() const noexcept { return fid; }
// Alias another font - caller guarantees not to Release
void SetID(FontID fid_) { fid = fid_; }
void SetID(FontID fid_) noexcept { fid = fid_; }
friend class Surface;
friend class SurfaceImpl;
};
@ -292,12 +338,12 @@ public:
* A surface abstracts a place to draw.
*/
class Surface {
private:
// Private so Surface objects can not be copied
Surface(const Surface &) {}
Surface &operator=(const Surface &) { return *this; }
public:
Surface() {}
Surface() noexcept = default;
Surface(const Surface &) = delete;
Surface(Surface &&) = delete;
Surface &operator=(const Surface &) = delete;
Surface &operator=(Surface &&) = delete;
virtual ~Surface() {}
static Surface *Allocate(int technology);
@ -312,27 +358,27 @@ public:
virtual int DeviceHeightFont(int points)=0;
virtual void MoveTo(int x_, int y_)=0;
virtual void LineTo(int x_, int y_)=0;
virtual void Polygon(Point *pts, int npts, ColourDesired fore, ColourDesired back)=0;
virtual void Polygon(Point *pts, size_t npts, ColourDesired fore, ColourDesired back)=0;
virtual void RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back)=0;
virtual void FillRectangle(PRectangle rc, ColourDesired back)=0;
virtual void FillRectangle(PRectangle rc, Surface &surfacePattern)=0;
virtual void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back)=0;
virtual void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill,
ColourDesired outline, int alphaOutline, int flags)=0;
enum class GradientOptions { leftToRight, topToBottom };
virtual void GradientRectangle(PRectangle rc, const std::vector<ColourStop> &stops, GradientOptions options)=0;
virtual void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) = 0;
virtual void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back)=0;
virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource)=0;
virtual void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back)=0;
virtual void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back)=0;
virtual void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore)=0;
virtual void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions)=0;
virtual XYPOSITION WidthText(Font &font_, const char *s, int len)=0;
virtual XYPOSITION WidthChar(Font &font_, char ch)=0;
virtual void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back) = 0;
virtual void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back) = 0;
virtual void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore) = 0;
virtual void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions) = 0;
virtual XYPOSITION WidthText(Font &font_, const char *s, int len) = 0;
virtual XYPOSITION Ascent(Font &font_)=0;
virtual XYPOSITION Descent(Font &font_)=0;
virtual XYPOSITION InternalLeading(Font &font_)=0;
virtual XYPOSITION ExternalLeading(Font &font_)=0;
virtual XYPOSITION Height(Font &font_)=0;
virtual XYPOSITION AverageCharWidth(Font &font_)=0;
@ -343,11 +389,6 @@ public:
virtual void SetDBCSMode(int codePage)=0;
};
/**
* A simple callback action passing one piece of untyped user data.
*/
typedef void (*CallBackAction)(void*);
/**
* Class to hide the details of window manipulation.
* Does not own the window which will normally have a longer life than this object.
@ -356,30 +397,31 @@ class Window {
protected:
WindowID wid;
public:
Window() : wid(0), cursorLast(cursorInvalid) {
Window() noexcept : wid(nullptr), cursorLast(cursorInvalid) {
}
Window(const Window &source) : wid(source.wid), cursorLast(cursorInvalid) {
}
virtual ~Window();
Window &operator=(WindowID wid_) {
Window(const Window &source) = delete;
Window(Window &&) = delete;
Window &operator=(WindowID wid_) noexcept {
wid = wid_;
cursorLast = cursorInvalid;
return *this;
}
WindowID GetID() const { return wid; }
bool Created() const { return wid != 0; }
Window &operator=(const Window &) = delete;
Window &operator=(Window &&) = delete;
virtual ~Window();
WindowID GetID() const noexcept { return wid; }
bool Created() const noexcept { return wid != nullptr; }
void Destroy();
bool HasFocus();
PRectangle GetPosition();
PRectangle GetPosition() const;
void SetPosition(PRectangle rc);
void SetPositionRelative(PRectangle rc, Window relativeTo);
PRectangle GetClientPosition();
void SetPositionRelative(PRectangle rc, const Window *relativeTo);
PRectangle GetClientPosition() const;
void Show(bool show=true);
void InvalidateAll();
void InvalidateRectangle(PRectangle rc);
virtual void SetFont(Font &font);
enum Cursor { cursorInvalid, cursorText, cursorArrow, cursorUp, cursorWait, cursorHoriz, cursorVert, cursorReverseArrow, cursorHand };
void SetCursor(Cursor curs);
void SetTitle(const char *s);
PRectangle GetMonitorRect(Point pt);
private:
Cursor cursorLast;
@ -389,13 +431,26 @@ private:
* Listbox management.
*/
// ScintillaBase implements IListBoxDelegate to receive ListBoxEvents from a ListBox
struct ListBoxEvent {
enum class EventType { selectionChange, doubleClick } event;
ListBoxEvent(EventType event_) noexcept : event(event_) {
}
};
class IListBoxDelegate {
public:
virtual void ListNotify(ListBoxEvent *plbe)=0;
};
class ListBox : public Window {
public:
ListBox();
virtual ~ListBox();
ListBox() noexcept;
~ListBox() override;
static ListBox *Allocate();
virtual void SetFont(Font &font)=0;
void SetFont(Font &font) override =0;
virtual void Create(Window &parent, int ctrlID, Point location, int lineHeight_, bool unicodeMode_, int technology_)=0;
virtual void SetAverageCharWidth(int width)=0;
virtual void SetVisibleRows(int rows)=0;
@ -412,7 +467,7 @@ public:
virtual void RegisterImage(int type, const char *xpm_data)=0;
virtual void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) = 0;
virtual void ClearRegisteredImages()=0;
virtual void SetDoubleClickAction(CallBackAction, void *)=0;
virtual void SetDelegate(IListBoxDelegate *lbDelegate)=0;
virtual void SetList(const char* list, char separator, char typesep)=0;
};
@ -422,27 +477,19 @@ public:
class Menu {
MenuID mid;
public:
Menu();
MenuID GetID() { return mid; }
Menu() noexcept;
MenuID GetID() const noexcept { return mid; }
void CreatePopUp();
void Destroy();
void Show(Point pt, Window &w);
};
class ElapsedTime {
long bigBit;
long littleBit;
public:
ElapsedTime();
double Duration(bool reset=false);
};
/**
* Dynamic Library (DLL/SO/...) loading
*/
class DynamicLibrary {
public:
virtual ~DynamicLibrary() {}
virtual ~DynamicLibrary() = default;
/// @return Pointer to function "name", or NULL on failure.
virtual Function FindFunction(const char *name) = 0;
@ -469,61 +516,34 @@ public:
* and chrome colour. Not a creatable object, more of a module with several functions.
*/
class Platform {
// Private so Platform objects can not be copied
Platform(const Platform &) {}
Platform &operator=(const Platform &) { return *this; }
public:
// Should be private because no new Platforms are ever created
// but gcc warns about this
Platform() {}
~Platform() {}
Platform() = default;
Platform(const Platform &) = delete;
Platform(Platform &&) = delete;
Platform &operator=(const Platform &) = delete;
Platform &operator=(Platform &&) = delete;
~Platform() = default;
static ColourDesired Chrome();
static ColourDesired ChromeHighlight();
static const char *DefaultFont();
static int DefaultFontSize();
static unsigned int DoubleClickTime();
static bool MouseButtonBounce();
static void DebugDisplay(const char *s);
static bool IsKeyDown(int key);
static long SendScintilla(
WindowID w, unsigned int msg, unsigned long wParam=0, long lParam=0);
static long SendScintillaPointer(
WindowID w, unsigned int msg, unsigned long wParam=0, void *lParam=0);
static bool IsDBCSLeadByte(int codePage, char ch);
static int DBCSCharLength(int codePage, const char *s);
static int DBCSCharMaxLength();
// These are utility functions not really tied to a platform
static int Minimum(int a, int b);
static int Maximum(int a, int b);
// Next three assume 16 bit shorts and 32 bit longs
static long LongFromTwoShorts(short a,short b) {
static constexpr long LongFromTwoShorts(short a,short b) noexcept {
return (a) | ((b) << 16);
}
static short HighShortFromLong(long x) {
return static_cast<short>(x >> 16);
}
static short LowShortFromLong(long x) {
return static_cast<short>(x & 0xffff);
}
static void DebugPrintf(const char *format, ...);
static bool ShowAssertionPopUps(bool assertionPopUps_);
static void Assert(const char *c, const char *file, int line) CLANG_ANALYZER_NORETURN;
static int Clamp(int val, int minVal, int maxVal);
};
#ifdef NDEBUG
#define PLATFORM_ASSERT(c) ((void)0)
#else
#ifdef SCI_NAMESPACE
#define PLATFORM_ASSERT(c) ((c) ? (void)(0) : Scintilla::Platform::Assert(#c, __FILE__, __LINE__))
#else
#define PLATFORM_ASSERT(c) ((c) ? (void)(0) : Platform::Assert(#c, __FILE__, __LINE__))
#endif
#endif
#ifdef SCI_NAMESPACE
}
#endif
#endif

View file

@ -134,6 +134,17 @@
#define SCLEX_TEHEX 119
#define SCLEX_JSON 120
#define SCLEX_EDIFACT 121
#define SCLEX_INDENT 122
#define SCLEX_MAXIMA 123
#define SCLEX_STATA 124
#define SCLEX_SAS 125
#define SCLEX_NIM 126
#define SCLEX_CIL 127
#define SCLEX_X12 128
#define SCLEX_DATAFLEX 129
#define SCLEX_HOLLYWOOD 130
#define SCLEX_RAKU 131
#define SCLEX_LPEG 999
#define SCLEX_AUTOMATIC 1000
#define SCE_P_DEFAULT 0
#define SCE_P_COMMENTLINE 1
@ -151,6 +162,10 @@
#define SCE_P_STRINGEOL 13
#define SCE_P_WORD2 14
#define SCE_P_DECORATOR 15
#define SCE_P_FSTRING 16
#define SCE_P_FCHARACTER 17
#define SCE_P_FTRIPLE 18
#define SCE_P_FTRIPLEDOUBLE 19
#define SCE_C_DEFAULT 0
#define SCE_C_COMMENT 1
#define SCE_C_COMMENTLINE 2
@ -502,6 +517,7 @@
#define SCE_ERR_GCC_INCLUDED_FROM 22
#define SCE_ERR_ESCSEQ 23
#define SCE_ERR_ESCSEQ_UNKNOWN 24
#define SCE_ERR_GCC_EXCERPT 25
#define SCE_ERR_ES_BLACK 40
#define SCE_ERR_ES_RED 41
#define SCE_ERR_ES_GREEN 42
@ -552,6 +568,10 @@
#define SCE_DIFF_DELETED 5
#define SCE_DIFF_ADDED 6
#define SCE_DIFF_CHANGED 7
#define SCE_DIFF_PATCH_ADD 8
#define SCE_DIFF_PATCH_DELETE 9
#define SCE_DIFF_REMOVED_PATCH_ADD 10
#define SCE_DIFF_REMOVED_PATCH_DELETE 11
#define SCE_CONF_DEFAULT 0
#define SCE_CONF_COMMENT 1
#define SCE_CONF_NUMBER 2
@ -667,6 +687,14 @@
#define SCE_MATLAB_OPERATOR 6
#define SCE_MATLAB_IDENTIFIER 7
#define SCE_MATLAB_DOUBLEQUOTESTRING 8
#define SCE_MAXIMA_OPERATOR 0
#define SCE_MAXIMA_COMMANDENDING 1
#define SCE_MAXIMA_COMMENT 2
#define SCE_MAXIMA_NUMBER 3
#define SCE_MAXIMA_STRING 4
#define SCE_MAXIMA_COMMAND 5
#define SCE_MAXIMA_VARIABLE 6
#define SCE_MAXIMA_UNKNOWN 7
#define SCE_SCRIPTOL_DEFAULT 0
#define SCE_SCRIPTOL_WHITE 1
#define SCE_SCRIPTOL_COMMENTLINE 2
@ -1807,6 +1835,130 @@
#define SCE_EDI_UNA 6
#define SCE_EDI_UNH 7
#define SCE_EDI_BADSEGMENT 8
#define SCE_STATA_DEFAULT 0
#define SCE_STATA_COMMENT 1
#define SCE_STATA_COMMENTLINE 2
#define SCE_STATA_COMMENTBLOCK 3
#define SCE_STATA_NUMBER 4
#define SCE_STATA_OPERATOR 5
#define SCE_STATA_IDENTIFIER 6
#define SCE_STATA_STRING 7
#define SCE_STATA_TYPE 8
#define SCE_STATA_WORD 9
#define SCE_STATA_GLOBAL_MACRO 10
#define SCE_STATA_MACRO 11
#define SCE_SAS_DEFAULT 0
#define SCE_SAS_COMMENT 1
#define SCE_SAS_COMMENTLINE 2
#define SCE_SAS_COMMENTBLOCK 3
#define SCE_SAS_NUMBER 4
#define SCE_SAS_OPERATOR 5
#define SCE_SAS_IDENTIFIER 6
#define SCE_SAS_STRING 7
#define SCE_SAS_TYPE 8
#define SCE_SAS_WORD 9
#define SCE_SAS_GLOBAL_MACRO 10
#define SCE_SAS_MACRO 11
#define SCE_SAS_MACRO_KEYWORD 12
#define SCE_SAS_BLOCK_KEYWORD 13
#define SCE_SAS_MACRO_FUNCTION 14
#define SCE_SAS_STATEMENT 15
#define SCE_NIM_DEFAULT 0
#define SCE_NIM_COMMENT 1
#define SCE_NIM_COMMENTDOC 2
#define SCE_NIM_COMMENTLINE 3
#define SCE_NIM_COMMENTLINEDOC 4
#define SCE_NIM_NUMBER 5
#define SCE_NIM_STRING 6
#define SCE_NIM_CHARACTER 7
#define SCE_NIM_WORD 8
#define SCE_NIM_TRIPLE 9
#define SCE_NIM_TRIPLEDOUBLE 10
#define SCE_NIM_BACKTICKS 11
#define SCE_NIM_FUNCNAME 12
#define SCE_NIM_STRINGEOL 13
#define SCE_NIM_NUMERROR 14
#define SCE_NIM_OPERATOR 15
#define SCE_NIM_IDENTIFIER 16
#define SCE_CIL_DEFAULT 0
#define SCE_CIL_COMMENT 1
#define SCE_CIL_COMMENTLINE 2
#define SCE_CIL_WORD 3
#define SCE_CIL_WORD2 4
#define SCE_CIL_WORD3 5
#define SCE_CIL_STRING 6
#define SCE_CIL_LABEL 7
#define SCE_CIL_OPERATOR 8
#define SCE_CIL_IDENTIFIER 9
#define SCE_CIL_STRINGEOL 10
#define SCE_X12_DEFAULT 0
#define SCE_X12_BAD 1
#define SCE_X12_ENVELOPE 2
#define SCE_X12_FUNCTIONGROUP 3
#define SCE_X12_TRANSACTIONSET 4
#define SCE_X12_SEGMENTHEADER 5
#define SCE_X12_SEGMENTEND 6
#define SCE_X12_SEP_ELEMENT 7
#define SCE_X12_SEP_SUBELEMENT 8
#define SCE_DF_DEFAULT 0
#define SCE_DF_IDENTIFIER 1
#define SCE_DF_METATAG 2
#define SCE_DF_IMAGE 3
#define SCE_DF_COMMENTLINE 4
#define SCE_DF_PREPROCESSOR 5
#define SCE_DF_PREPROCESSOR2 6
#define SCE_DF_NUMBER 7
#define SCE_DF_HEXNUMBER 8
#define SCE_DF_WORD 9
#define SCE_DF_STRING 10
#define SCE_DF_STRINGEOL 11
#define SCE_DF_SCOPEWORD 12
#define SCE_DF_OPERATOR 13
#define SCE_DF_ICODE 14
#define SCE_HOLLYWOOD_DEFAULT 0
#define SCE_HOLLYWOOD_COMMENT 1
#define SCE_HOLLYWOOD_COMMENTBLOCK 2
#define SCE_HOLLYWOOD_NUMBER 3
#define SCE_HOLLYWOOD_KEYWORD 4
#define SCE_HOLLYWOOD_STDAPI 5
#define SCE_HOLLYWOOD_PLUGINAPI 6
#define SCE_HOLLYWOOD_PLUGINMETHOD 7
#define SCE_HOLLYWOOD_STRING 8
#define SCE_HOLLYWOOD_STRINGBLOCK 9
#define SCE_HOLLYWOOD_PREPROCESSOR 10
#define SCE_HOLLYWOOD_OPERATOR 11
#define SCE_HOLLYWOOD_IDENTIFIER 12
#define SCE_HOLLYWOOD_CONSTANT 13
#define SCE_HOLLYWOOD_HEXNUMBER 14
#define SCE_RAKU_DEFAULT 0
#define SCE_RAKU_ERROR 1
#define SCE_RAKU_COMMENTLINE 2
#define SCE_RAKU_COMMENTEMBED 3
#define SCE_RAKU_POD 4
#define SCE_RAKU_CHARACTER 5
#define SCE_RAKU_HEREDOC_Q 6
#define SCE_RAKU_HEREDOC_QQ 7
#define SCE_RAKU_STRING 8
#define SCE_RAKU_STRING_Q 9
#define SCE_RAKU_STRING_QQ 10
#define SCE_RAKU_STRING_Q_LANG 11
#define SCE_RAKU_STRING_VAR 12
#define SCE_RAKU_REGEX 13
#define SCE_RAKU_REGEX_VAR 14
#define SCE_RAKU_ADVERB 15
#define SCE_RAKU_NUMBER 16
#define SCE_RAKU_PREPROCESSOR 17
#define SCE_RAKU_OPERATOR 18
#define SCE_RAKU_WORD 19
#define SCE_RAKU_FUNCTION 20
#define SCE_RAKU_IDENTIFIER 21
#define SCE_RAKU_TYPEDEF 22
#define SCE_RAKU_MU 23
#define SCE_RAKU_POSITIONAL 24
#define SCE_RAKU_ASSOCIATIVE 25
#define SCE_RAKU_CALLABLE 26
#define SCE_RAKU_GRAMMAR 27
#define SCE_RAKU_CLASS 28
/* --Autogenerated -- end of section automatically generated from Scintilla.iface */
#endif

View file

@ -9,13 +9,21 @@
#ifndef SCI_POSITION_H
#define SCI_POSITION_H
#include <stddef.h>
// Basic signed type used throughout interface
typedef int Sci_Position;
typedef ptrdiff_t Sci_Position;
// Unsigned variant used for ILexer::Lex and ILexer::Fold
typedef unsigned int Sci_PositionU;
typedef size_t Sci_PositionU;
// For Sci_CharacterRange which is defined as long to be compatible with Win32 CHARRANGE
typedef long Sci_PositionCR;
#ifdef _WIN32
#define SCI_METHOD __stdcall
#else
#define SCI_METHOD
#endif
#endif

View file

@ -27,14 +27,7 @@ int Scintilla_LinkLexers(void);
#endif
// Include header that defines basic numeric types.
#if defined(_MSC_VER)
// Older releases of MSVC did not have stdint.h.
#include <stddef.h>
#elif defined( __VMS )
#include <inttypes.h>
#else
#include <stdint.h>
#endif
// Define uptr_t, an unsigned integer type large enough to hold a pointer.
typedef uintptr_t uptr_t;
@ -45,6 +38,8 @@ typedef intptr_t sptr_t;
typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, sptr_t lParam);
#ifndef SCI_DISABLE_AUTOGENERATED
/* ++Autogenerated -- start of section automatically generated from Scintilla.iface */
#define INVALID_POSITION -1
#define SCI_START 2000
@ -70,6 +65,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_CANREDO 2016
#define SCI_MARKERLINEFROMHANDLE 2017
#define SCI_MARKERDELETEHANDLE 2018
#define SCI_MARKERHANDLEFROMLINE 2732
#define SCI_MARKERNUMBERFROMLINE 2733
#define SCI_GETUNDOCOLLECTION 2019
#define SCWS_INVISIBLE 0
#define SCWS_VISIBLEALWAYS 1
@ -100,6 +97,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_SETBUFFEREDDRAW 2035
#define SCI_SETTABWIDTH 2036
#define SCI_GETTABWIDTH 2121
#define SCI_SETTABMINIMUMWIDTH 2724
#define SCI_GETTABMINIMUMWIDTH 2725
#define SCI_CLEARTABSTOPS 2675
#define SCI_ADDTABSTOP 2676
#define SCI_GETNEXTTABSTOP 2677
@ -109,6 +108,13 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SC_IME_INLINE 1
#define SCI_GETIMEINTERACTION 2678
#define SCI_SETIMEINTERACTION 2679
#define SC_ALPHA_TRANSPARENT 0
#define SC_ALPHA_OPAQUE 255
#define SC_ALPHA_NOALPHA 256
#define SC_CURSORNORMAL -1
#define SC_CURSORARROW 2
#define SC_CURSORWAIT 4
#define SC_CURSORREVERSEARROW 7
#define MARKER_MAX 31
#define SC_MARK_CIRCLE 0
#define SC_MARK_ROUNDRECT 1
@ -142,6 +148,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SC_MARK_UNDERLINE 29
#define SC_MARK_RGBAIMAGE 30
#define SC_MARK_BOOKMARK 31
#define SC_MARK_VERTICALBOOKMARK 32
#define SC_MARK_CHARACTER 10000
#define SC_MARKNUM_FOLDEREND 25
#define SC_MARKNUM_FOLDEROPENMID 26
@ -273,6 +280,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_SETCARETPERIOD 2076
#define SCI_SETWORDCHARS 2077
#define SCI_GETWORDCHARS 2646
#define SCI_SETCHARACTERCATEGORYOPTIMIZATION 2720
#define SCI_GETCHARACTERCATEGORYOPTIMIZATION 2721
#define SCI_BEGINUNDOACTION 2078
#define SCI_ENDUNDOACTION 2079
#define INDIC_PLAIN 0
@ -295,14 +304,16 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define INDIC_TEXTFORE 17
#define INDIC_POINT 18
#define INDIC_POINTCHARACTER 19
#define INDIC_GRADIENT 20
#define INDIC_GRADIENTCENTRE 21
#define INDIC_CONTAINER 8
#define INDIC_IME 32
#define INDIC_IME_MAX 35
#define INDIC_MAX 35
#define INDIC_CONTAINER 8
#define INDIC0_MASK 0x20
#define INDIC1_MASK 0x40
#define INDIC2_MASK 0x80
#define INDICS_MASK 0xE0
#define INDICATOR_CONTAINER 8
#define INDICATOR_IME 32
#define INDICATOR_IME_MAX 35
#define INDICATOR_MAX 35
#define SCI_INDICSETSTYLE 2080
#define SCI_INDICGETSTYLE 2081
#define SCI_INDICSETFORE 2082
@ -322,8 +333,6 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_SETWHITESPACEBACK 2085
#define SCI_SETWHITESPACESIZE 2086
#define SCI_GETWHITESPACESIZE 2087
#define SCI_SETSTYLEBITS 2090
#define SCI_GETSTYLEBITS 2091
#define SCI_SETLINESTATE 2092
#define SCI_GETLINESTATE 2093
#define SCI_GETMAXLINESTATE 2094
@ -331,6 +340,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_SETCARETLINEVISIBLE 2096
#define SCI_GETCARETLINEBACK 2097
#define SCI_SETCARETLINEBACK 2098
#define SCI_GETCARETLINEFRAME 2704
#define SCI_SETCARETLINEFRAME 2705
#define SCI_STYLESETCHANGEABLE 2099
#define SCI_AUTOCSHOW 2100
#define SCI_AUTOCCANCEL 2101
@ -370,6 +381,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_GETLINEINDENTPOSITION 2128
#define SCI_GETCOLUMN 2129
#define SCI_COUNTCHARACTERS 2633
#define SCI_COUNTCODEUNITS 2715
#define SCI_SETHSCROLLBAR 2130
#define SCI_GETHSCROLLBAR 2131
#define SC_IV_NONE 0
@ -397,8 +409,10 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SC_PRINT_BLACKONWHITE 2
#define SC_PRINT_COLOURONWHITE 3
#define SC_PRINT_COLOURONWHITEDEFAULTBG 4
#define SC_PRINT_SCREENCOLOURS 5
#define SCI_SETPRINTCOLOURMODE 2148
#define SCI_GETPRINTCOLOURMODE 2149
#define SCFIND_NONE 0x0
#define SCFIND_WHOLEWORD 0x2
#define SCFIND_MATCHCASE 0x4
#define SCFIND_WORDSTART 0x00100000
@ -448,8 +462,12 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_GETCARETWIDTH 2189
#define SCI_SETTARGETSTART 2190
#define SCI_GETTARGETSTART 2191
#define SCI_SETTARGETSTARTVIRTUALSPACE 2728
#define SCI_GETTARGETSTARTVIRTUALSPACE 2729
#define SCI_SETTARGETEND 2192
#define SCI_GETTARGETEND 2193
#define SCI_SETTARGETENDVIRTUALSPACE 2730
#define SCI_GETTARGETENDVIRTUALSPACE 2731
#define SCI_SETTARGETRANGE 2686
#define SCI_GETTARGETTEXT 2687
#define SCI_TARGETFROMSELECTION 2287
@ -493,6 +511,9 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SC_FOLDDISPLAYTEXT_STANDARD 1
#define SC_FOLDDISPLAYTEXT_BOXED 2
#define SCI_FOLDDISPLAYTEXTSETSTYLE 2701
#define SCI_FOLDDISPLAYTEXTGETSTYLE 2707
#define SCI_SETDEFAULTFOLDDISPLAYTEXT 2722
#define SCI_GETDEFAULTFOLDDISPLAYTEXT 2723
#define SC_FOLDACTION_CONTRACT 0
#define SC_FOLDACTION_EXPAND 1
#define SC_FOLDACTION_TOGGLE 2
@ -552,6 +573,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SC_WRAPINDENT_FIXED 0
#define SC_WRAPINDENT_SAME 1
#define SC_WRAPINDENT_INDENT 2
#define SC_WRAPINDENT_DEEPINDENT 3
#define SCI_SETWRAPINDENTMODE 2472
#define SCI_GETWRAPINDENTMODE 2473
#define SC_CACHE_NONE 0
@ -595,6 +617,10 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_LINESSPLIT 2289
#define SCI_SETFOLDMARGINCOLOUR 2290
#define SCI_SETFOLDMARGINHICOLOUR 2291
#define SC_ACCESSIBILITY_DISABLED 0
#define SC_ACCESSIBILITY_ENABLED 1
#define SCI_SETACCESSIBILITY 2702
#define SCI_GETACCESSIBILITY 2703
#define SCI_LINEDOWN 2300
#define SCI_LINEDOWNEXTEND 2301
#define SCI_LINEUP 2302
@ -636,6 +662,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_LINECUT 2337
#define SCI_LINEDELETE 2338
#define SCI_LINETRANSPOSE 2339
#define SCI_LINEREVERSE 2354
#define SCI_LINEDUPLICATE 2404
#define SCI_LOWERCASE 2340
#define SCI_UPPERCASE 2341
@ -660,6 +687,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_BRACEBADLIGHT 2352
#define SCI_BRACEBADLIGHTINDICATOR 2499
#define SCI_BRACEMATCH 2353
#define SCI_BRACEMATCHNEXT 2369
#define SCI_GETVIEWEOL 2355
#define SCI_SETVIEWEOL 2356
#define SCI_GETDOCPOINTER 2357
@ -677,6 +705,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_SETEDGECOLOUR 2365
#define SCI_MULTIEDGEADDLINE 2694
#define SCI_MULTIEDGECLEARALL 2695
#define SCI_GETMULTIEDGECOLUMN 2749
#define SCI_SEARCHANCHOR 2366
#define SCI_SEARCHNEXT 2367
#define SCI_SEARCHPREV 2368
@ -688,10 +717,16 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_SELECTIONISRECTANGLE 2372
#define SCI_SETZOOM 2373
#define SCI_GETZOOM 2374
#define SC_DOCUMENTOPTION_DEFAULT 0
#define SC_DOCUMENTOPTION_STYLES_NONE 0x1
#define SC_DOCUMENTOPTION_TEXT_LARGE 0x100
#define SCI_CREATEDOCUMENT 2375
#define SCI_ADDREFDOCUMENT 2376
#define SCI_RELEASEDOCUMENT 2377
#define SCI_GETDOCUMENTOPTIONS 2379
#define SCI_GETMODEVENTMASK 2378
#define SCI_SETCOMMANDEVENTS 2717
#define SCI_GETCOMMANDEVENTS 2718
#define SCI_SETFOCUS 2380
#define SCI_GETFOCUS 2381
#define SC_STATUS_OK 0
@ -705,10 +740,6 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_GETMOUSEDOWNCAPTURES 2385
#define SCI_SETMOUSEWHEELCAPTURES 2696
#define SCI_GETMOUSEWHEELCAPTURES 2697
#define SC_CURSORNORMAL -1
#define SC_CURSORARROW 2
#define SC_CURSORWAIT 4
#define SC_CURSORREVERSEARROW 7
#define SCI_SETCURSOR 2386
#define SCI_GETCURSOR 2387
#define SCI_SETCONTROLCHARSYMBOL 2388
@ -749,6 +780,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_POSITIONBEFORE 2417
#define SCI_POSITIONAFTER 2418
#define SCI_POSITIONRELATIVE 2670
#define SCI_POSITIONRELATIVECODEUNITS 2716
#define SCI_COPYRANGE 2419
#define SCI_COPYTEXT 2420
#define SC_SEL_STREAM 0
@ -757,6 +789,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SC_SEL_THIN 3
#define SCI_SETSELECTIONMODE 2422
#define SCI_GETSELECTIONMODE 2423
#define SCI_GETMOVEEXTENDSSELECTION 2706
#define SCI_GETLINESELSTARTPOSITION 2424
#define SCI_GETLINESELENDPOSITION 2425
#define SCI_LINEDOWNRECTEXTEND 2426
@ -801,23 +834,24 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_SETLENGTHFORENCODE 2448
#define SCI_ENCODEDFROMUTF8 2449
#define SCI_FINDCOLUMN 2456
#define SCI_GETCARETSTICKY 2457
#define SCI_SETCARETSTICKY 2458
#define SC_CARETSTICKY_OFF 0
#define SC_CARETSTICKY_ON 1
#define SC_CARETSTICKY_WHITESPACE 2
#define SCI_GETCARETSTICKY 2457
#define SCI_SETCARETSTICKY 2458
#define SCI_TOGGLECARETSTICKY 2459
#define SCI_SETPASTECONVERTENDINGS 2467
#define SCI_GETPASTECONVERTENDINGS 2468
#define SCI_SELECTIONDUPLICATE 2469
#define SC_ALPHA_TRANSPARENT 0
#define SC_ALPHA_OPAQUE 255
#define SC_ALPHA_NOALPHA 256
#define SCI_SETCARETLINEBACKALPHA 2470
#define SCI_GETCARETLINEBACKALPHA 2471
#define CARETSTYLE_INVISIBLE 0
#define CARETSTYLE_LINE 1
#define CARETSTYLE_BLOCK 2
#define CARETSTYLE_OVERSTRIKE_BAR 0
#define CARETSTYLE_OVERSTRIKE_BLOCK 0x10
#define CARETSTYLE_INS_MASK 0xF
#define CARETSTYLE_BLOCK_AFTER 0x100
#define SCI_SETCARETSTYLE 2512
#define SCI_GETCARETSTYLE 2513
#define SCI_SETINDICATORCURRENT 2500
@ -876,6 +910,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_ANNOTATIONGETSTYLEOFFSET 2551
#define SCI_RELEASEALLEXTENDEDSTYLES 2552
#define SCI_ALLOCATEEXTENDEDSTYLES 2553
#define UNDO_NONE 0
#define UNDO_MAY_COALESCE 1
#define SCI_ADDUNDOACTION 2560
#define SCI_CHARPOSITIONFROMPOINT 2561
@ -908,7 +943,9 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_GETSELECTIONNANCHORVIRTUALSPACE 2583
#define SCI_SETSELECTIONNSTART 2584
#define SCI_GETSELECTIONNSTART 2585
#define SCI_GETSELECTIONNSTARTVIRTUALSPACE 2726
#define SCI_SETSELECTIONNEND 2586
#define SCI_GETSELECTIONNENDVIRTUALSPACE 2727
#define SCI_GETSELECTIONNEND 2587
#define SCI_SETRECTANGULARSELECTIONCARET 2588
#define SCI_GETRECTANGULARSELECTIONCARET 2589
@ -972,6 +1009,18 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_SETREPRESENTATION 2665
#define SCI_GETREPRESENTATION 2666
#define SCI_CLEARREPRESENTATION 2667
#define SCI_EOLANNOTATIONSETTEXT 2740
#define SCI_EOLANNOTATIONGETTEXT 2741
#define SCI_EOLANNOTATIONSETSTYLE 2742
#define SCI_EOLANNOTATIONGETSTYLE 2743
#define SCI_EOLANNOTATIONCLEARALL 2744
#define EOLANNOTATION_HIDDEN 0
#define EOLANNOTATION_STANDARD 1
#define EOLANNOTATION_BOXED 2
#define SCI_EOLANNOTATIONSETVISIBLE 2745
#define SCI_EOLANNOTATIONGETVISIBLE 2746
#define SCI_EOLANNOTATIONSETSTYLEOFFSET 2747
#define SCI_EOLANNOTATIONGETSTYLEOFFSET 2748
#define SCI_STARTRECORD 3001
#define SCI_STOPRECORD 3002
#define SCI_SETLEXER 4001
@ -985,7 +1034,6 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_GETPROPERTY 4008
#define SCI_GETPROPERTYEXPANDED 4009
#define SCI_GETPROPERTYINT 4010
#define SCI_GETSTYLEBITSNEEDED 4011
#define SCI_GETLEXERLANGUAGE 4012
#define SCI_PRIVATELEXERCALL 4013
#define SCI_PROPERTYNAMES 4014
@ -1005,6 +1053,11 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_SETIDENTIFIERS 4024
#define SCI_DISTANCETOSECONDARYSTYLES 4025
#define SCI_GETSUBSTYLEBASES 4026
#define SCI_GETNAMEDSTYLES 4029
#define SCI_NAMEOFSTYLE 4030
#define SCI_TAGSOFSTYLE 4031
#define SCI_DESCRIPTIONOFSTYLE 4032
#define SC_MOD_NONE 0x0
#define SC_MOD_INSERTTEXT 0x1
#define SC_MOD_DELETETEXT 0x2
#define SC_MOD_CHANGESTYLE 0x4
@ -1027,7 +1080,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SC_MOD_LEXERSTATE 0x80000
#define SC_MOD_INSERTCHECK 0x100000
#define SC_MOD_CHANGETABSTOPS 0x200000
#define SC_MODEVENTMASKALL 0x3FFFFF
#define SC_MOD_CHANGEEOLANNOTATION 0x400000
#define SC_MODEVENTMASKALL 0x7FFFFF
#define SC_UPDATE_CONTENT 0x1
#define SC_UPDATE_SELECTION 0x2
#define SC_UPDATE_V_SCROLL 0x4
@ -1066,6 +1120,9 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SC_AC_TAB 3
#define SC_AC_NEWLINE 4
#define SC_AC_COMMAND 5
#define SC_CHARACTERSOURCE_DIRECT_INPUT 0
#define SC_CHARACTERSOURCE_TENTATIVE_INPUT 1
#define SC_CHARACTERSOURCE_IME_RESULT 2
#define SCN_STYLENEEDED 2000
#define SCN_CHARADDED 2001
#define SCN_SAVEPOINTREACHED 2002
@ -1097,8 +1154,21 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCN_FOCUSOUT 2029
#define SCN_AUTOCCOMPLETED 2030
#define SCN_MARGINRIGHTCLICK 2031
#define SCN_AUTOCSELECTIONCHANGE 2032
#ifndef SCI_DISABLE_PROVISIONAL
#define SC_LINECHARACTERINDEX_NONE 0
#define SC_LINECHARACTERINDEX_UTF32 1
#define SC_LINECHARACTERINDEX_UTF16 2
#define SCI_GETLINECHARACTERINDEX 2710
#define SCI_ALLOCATELINECHARACTERINDEX 2711
#define SCI_RELEASELINECHARACTERINDEX 2712
#define SCI_LINEFROMINDEXPOSITION 2713
#define SCI_INDEXPOSITIONFROMLINE 2714
#endif
/* --Autogenerated -- end of section automatically generated from Scintilla.iface */
#endif
/* These structures are defined to be exactly the same shape as the Win32
* CHARRANGE, TEXTRANGE, FINDTEXTEX, FORMATRANGE, and NMHDR structs.
* So older code that treats Scintilla as a RichEdit will work. */
@ -1192,6 +1262,7 @@ struct SCNotification {
int updated; /* SCN_UPDATEUI */
int listCompletionMethod;
/* SCN_AUTOCSELECTION, SCN_AUTOCCOMPLETED, SCN_USERLISTSELECTION, */
int characterSource; /* SCN_CHARADDED */
};
#ifdef INCLUDE_DEPRECATED_FEATURES
@ -1205,6 +1276,17 @@ struct SCNotification {
#define RangeToFormat Sci_RangeToFormat
#define NotifyHeader Sci_NotifyHeader
#endif
#define SCI_SETSTYLEBITS 2090
#define SCI_GETSTYLEBITS 2091
#define SCI_GETSTYLEBITSNEEDED 4011
#define INDIC0_MASK 0x20
#define INDIC1_MASK 0x40
#define INDIC2_MASK 0x80
#define INDICS_MASK 0xE0
#endif
#include "Compat.h"
#endif

File diff suppressed because it is too large Load diff

View file

@ -26,9 +26,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
// Return values for GetOperatorType

View file

@ -24,9 +24,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsAWordChar(const int ch) {
return (ch < 0x80 && (isalnum(ch) || ch == '_'));

View file

@ -1,4 +1,5 @@
// Scintilla source code edit control
// @file LexASY.cxx
//Author: instanton (email: soft_share<at>126<dot>com)
// The License.txt file describes the conditions under which this software may be distributed.
@ -19,9 +20,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static void ColouriseAsyDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
WordList *keywordlists[], Accessor &styler) {

View file

@ -1,6 +1,6 @@
// Scintilla source code edit control
// @file LexAU3.cxx
// Lexer for AutoIt3 http://www.hiddensoft.com/autoit3
// Lexer for AutoIt3 https://www.autoitscript.com/site/
// by Jos van der Zande, jvdzande@yahoo.com
//
// Changes:
@ -68,9 +68,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsTypeCharacter(const int ch)
{

View file

@ -25,9 +25,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsAWordChar(const int ch) {

View file

@ -24,9 +24,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsAWordChar(const int ch) {
return (ch < 0x80) && (isalnum(ch) || ch == '_');

View file

@ -1,5 +1,5 @@
// Scintilla source code edit control
/** @file LexABAQUS.cxx
/** @file LexAbaqus.cxx
** Lexer for ABAQUS. Based on the lexer for APDL by Hadar Raz.
** By Sergio Lucato.
** Sort of completely rewritten by Gertjan Kloosterman
@ -26,9 +26,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsAKeywordChar(const int ch) {
return (ch < 0x80 && (isalnum(ch) || (ch == '_') || (ch == ' ')));

View file

@ -25,9 +25,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
/*
* Interface

View file

@ -30,10 +30,9 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"
#include "DefaultLexer.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsAWordChar(const int ch) {
return (ch < 0x80) && (isalnum(ch) || ch == '.' ||
@ -81,6 +80,7 @@ struct OptionsAsm {
std::string foldExplicitEnd;
bool foldExplicitAnywhere;
bool foldCompact;
std::string commentChar;
OptionsAsm() {
delimiter = "";
fold = false;
@ -91,6 +91,7 @@ struct OptionsAsm {
foldExplicitEnd = "";
foldExplicitAnywhere = false;
foldCompact = true;
commentChar = "";
}
};
@ -135,11 +136,14 @@ struct OptionSetAsm : public OptionSet<OptionsAsm> {
DefineProperty("fold.compact", &OptionsAsm::foldCompact);
DefineProperty("lexer.as.comment.character", &OptionsAsm::commentChar,
"Overrides the default comment character (which is ';' for asm and '#' for as).");
DefineWordListSets(asmWordListDesc);
}
};
class LexerAsm : public ILexer {
class LexerAsm : public DefaultLexer {
WordList cpuInstruction;
WordList mathInstruction;
WordList registers;
@ -152,44 +156,47 @@ class LexerAsm : public ILexer {
OptionSetAsm osAsm;
int commentChar;
public:
LexerAsm(int commentChar_) {
LexerAsm(const char *languageName_, int language_, int commentChar_) : DefaultLexer(languageName_, language_) {
commentChar = commentChar_;
}
virtual ~LexerAsm() {
}
void SCI_METHOD Release() {
void SCI_METHOD Release() override {
delete this;
}
int SCI_METHOD Version() const {
return lvOriginal;
int SCI_METHOD Version() const override {
return lvIdentity;
}
const char * SCI_METHOD PropertyNames() {
const char * SCI_METHOD PropertyNames() override {
return osAsm.PropertyNames();
}
int SCI_METHOD PropertyType(const char *name) {
int SCI_METHOD PropertyType(const char *name) override {
return osAsm.PropertyType(name);
}
const char * SCI_METHOD DescribeProperty(const char *name) {
const char * SCI_METHOD DescribeProperty(const char *name) override {
return osAsm.DescribeProperty(name);
}
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val);
const char * SCI_METHOD DescribeWordListSets() {
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
const char * SCI_METHOD PropertyGet(const char *key) override {
return osAsm.PropertyGet(key);
}
const char * SCI_METHOD DescribeWordListSets() override {
return osAsm.DescribeWordListSets();
}
Sci_Position SCI_METHOD WordListSet(int n, const char *wl);
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess);
void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess);
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 *) {
void * SCI_METHOD PrivateCall(int, void *) override {
return 0;
}
static ILexer *LexerFactoryAsm() {
return new LexerAsm(';');
return new LexerAsm("asm", SCLEX_ASM, ';');
}
static ILexer *LexerFactoryAs() {
return new LexerAsm('#');
return new LexerAsm("as", SCLEX_AS, '#');
}
};
@ -243,6 +250,9 @@ Sci_Position SCI_METHOD LexerAsm::WordListSet(int n, const char *wl) {
void SCI_METHOD LexerAsm::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) {
LexAccessor styler(pAccess);
const char commentCharacter = options.commentChar.empty() ?
commentChar : options.commentChar.front();
// Do not leak onto next line
if (initStyle == SCE_ASM_STRINGEOL)
initStyle = SCE_ASM_DEFAULT;
@ -348,7 +358,7 @@ void SCI_METHOD LexerAsm::Lex(Sci_PositionU startPos, Sci_Position length, int i
// Determine if a new state should be entered.
if (sc.state == SCE_ASM_DEFAULT) {
if (sc.ch == commentChar){
if (sc.ch == commentCharacter) {
sc.SetState(SCE_ASM_COMMENT);
} else if (IsASCII(sc.ch) && (isdigit(sc.ch) || (sc.ch == '.' && IsASCII(sc.chNext) && isdigit(sc.chNext)))) {
sc.SetState(SCE_ASM_NUMBER);

View file

@ -23,9 +23,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
// Some char test functions
static bool isAsn1Number(int ch)

View file

@ -4,6 +4,7 @@
** Based heavily on LexCPP.cxx
**/
// Copyright 2001- by Vamsi Potluru <vamsi@who.net> & Praveen Ambekar <ambekarpraveen@yahoo.com>
// Maintainer Email: oirfeodent@yahoo.co.in
// The License.txt file describes the conditions under which this software may be distributed.
// C standard library
@ -33,10 +34,9 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"
#include "DefaultLexer.h"
# ifdef SCI_NAMESPACE
using namespace Scintilla;
# endif
namespace {
// Use an unnamed namespace to protect the functions and classes from name conflicts
@ -129,7 +129,7 @@ static inline bool IsAnOperator(int ch) {
return false;
}
static inline int IsAnyOtherIdentifier(char *s, int sLength) {
static inline int IsAnyOtherIdentifier(char *s, Sci_Position sLength) {
/* IsAnyOtherIdentifier uses standard templates used in baan.
The matching template is shown as comments just above the return condition.
@ -380,7 +380,7 @@ public:
}
class LexerBaan : public ILexer {
class LexerBaan : public DefaultLexer {
WordListAbridged keywords;
WordListAbridged keywords2;
WordListAbridged keywords3;
@ -393,45 +393,49 @@ class LexerBaan : public ILexer {
OptionsBaan options;
OptionSetBaan osBaan;
public:
LexerBaan() {
LexerBaan() : DefaultLexer("baan", SCLEX_BAAN) {
}
virtual ~LexerBaan() {
}
int SCI_METHOD Version() const {
return lvOriginal;
int SCI_METHOD Version() const override {
return lvIdentity;
}
void SCI_METHOD Release() {
void SCI_METHOD Release() override {
delete this;
}
const char * SCI_METHOD PropertyNames() {
const char * SCI_METHOD PropertyNames() override {
return osBaan.PropertyNames();
}
int SCI_METHOD PropertyType(const char * name) {
int SCI_METHOD PropertyType(const char * name) override {
return osBaan.PropertyType(name);
}
const char * SCI_METHOD DescribeProperty(const char * name) {
const char * SCI_METHOD DescribeProperty(const char * name) override {
return osBaan.DescribeProperty(name);
}
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val);
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
const char * SCI_METHOD DescribeWordListSets() {
const char * SCI_METHOD PropertyGet(const char *key) override {
return osBaan.PropertyGet(key);
}
const char * SCI_METHOD DescribeWordListSets() override {
return osBaan.DescribeWordListSets();
}
Sci_Position SCI_METHOD WordListSet(int n, const char *wl);
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);
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);
void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override;
void * SCI_METHOD PrivateCall(int, void *) {
void * SCI_METHOD PrivateCall(int, void *) override {
return NULL;
}
@ -504,10 +508,12 @@ void SCI_METHOD LexerBaan::Lex(Sci_PositionU startPos, Sci_Position length, int
bool lineHasPreProc = false;
bool lineIgnoreString = false;
bool lineHasDefines = false;
bool numberIsHex = false;
char word[1000];
int wordlen = 0;
std::string preProcessorTags[11] = { "#define", "#elif", "#else", "#endif",
std::string preProcessorTags[13] = { "#context_off", "#context_on",
"#define", "#elif", "#else", "#endif",
"#ident", "#if", "#ifdef", "#ifndef",
"#include", "#pragma", "#undef" };
LexAccessor styler(pAccess);
@ -521,9 +527,18 @@ void SCI_METHOD LexerBaan::Lex(Sci_PositionU startPos, Sci_Position length, int
sc.SetState(SCE_BAAN_DEFAULT);
break;
case SCE_BAAN_NUMBER:
if (!IsAWordChar(sc.ch)) {
if (IsASpaceOrTab(sc.ch) || sc.ch == '\r' || sc.ch == '\n' || IsAnOperator(sc.ch)) {
sc.SetState(SCE_BAAN_DEFAULT);
}
else if ((numberIsHex && !(MakeLowerCase(sc.ch) == 'x' || MakeLowerCase(sc.ch) == 'e' ||
IsADigit(sc.ch, 16) || sc.ch == '.' || sc.ch == '-' || sc.ch == '+')) ||
(!numberIsHex && !(MakeLowerCase(sc.ch) == 'e' || IsADigit(sc.ch)
|| sc.ch == '.' || sc.ch == '-' || sc.ch == '+'))) {
// check '-' for possible -10e-5. Add '+' as well.
numberIsHex = false;
sc.ChangeState(SCE_BAAN_IDENTIFIER);
sc.SetState(SCE_BAAN_DEFAULT);
}
break;
case SCE_BAAN_IDENTIFIER:
if (!IsAWordChar(sc.ch)) {
@ -556,7 +571,10 @@ void SCI_METHOD LexerBaan::Lex(Sci_PositionU startPos, Sci_Position length, int
sc.ChangeState(SCE_BAAN_WORD2);
}
else if ((keywords3.kwHasSection && (sc.ch == ':')) ? keywords3.Contains(s1) : keywords3.Contains(s)) {
sc.ChangeState(SCE_BAAN_WORD3);
if (sc.ch == '(')
sc.ChangeState(SCE_BAAN_WORD3);
else
sc.ChangeState(SCE_BAAN_IDENTIFIER);
}
else if ((keywords4.kwHasSection && (sc.ch == ':')) ? keywords4.Contains(s1) : keywords4.Contains(s)) {
sc.ChangeState(SCE_BAAN_WORD4);
@ -606,7 +624,7 @@ void SCI_METHOD LexerBaan::Lex(Sci_PositionU startPos, Sci_Position length, int
}
break;
case SCE_BAAN_COMMENT:
if (sc.atLineEnd) {
if (sc.ch == '\r' || sc.ch == '\n') {
sc.SetState(SCE_BAAN_DEFAULT);
}
break;
@ -638,7 +656,13 @@ void SCI_METHOD LexerBaan::Lex(Sci_PositionU startPos, Sci_Position length, int
// Determine if a new state should be entered.
if (sc.state == SCE_BAAN_DEFAULT) {
if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))
|| ((sc.ch == '-' || sc.ch == '+') && (IsADigit(sc.chNext) || sc.chNext == '.'))
|| (MakeLowerCase(sc.ch) == 'e' && (IsADigit(sc.chNext) || sc.chNext == '+' || sc.chNext == '-'))) {
if ((sc.ch == '0' && MakeLowerCase(sc.chNext) == 'x') ||
((sc.ch == '-' || sc.ch == '+') && sc.chNext == '0' && MakeLowerCase(sc.GetRelativeCharacter(2)) == 'x')){
numberIsHex = true;
}
sc.SetState(SCE_BAAN_NUMBER);
}
else if (sc.MatchIgnoreCase("dllusage") || sc.MatchIgnoreCase("functionusage")) {
@ -670,7 +694,7 @@ void SCI_METHOD LexerBaan::Lex(Sci_PositionU startPos, Sci_Position length, int
word[wordlen++] = sc.ch;
word[wordlen++] = '\0';
}
if (!wordInArray(word, preProcessorTags, 11))
if (!wordInArray(word, preProcessorTags, 13))
// Colorise only preprocessor built in Baan.
sc.ChangeState(SCE_BAAN_IDENTIFIER);
if (strcmp(word, "#pragma") == 0 || strcmp(word, "#include") == 0) {
@ -697,6 +721,7 @@ void SCI_METHOD LexerBaan::Lex(Sci_PositionU startPos, Sci_Position length, int
lineHasPreProc = false;
lineIgnoreString = false;
lineHasDefines = false;
numberIsHex = false;
}
if (!IsASpace(sc.ch)) {
visibleChars++;
@ -781,9 +806,10 @@ void SCI_METHOD LexerBaan::Fold(Sci_PositionU startPos, Sci_Position length, int
else if (style == SCE_BAAN_PREPROCESSOR) {
// folds #ifdef/#if/#ifndef - they are not part of the IsPreProcLine folding.
if (ch == '#') {
if (styler.Match(i, "#ifdef") || styler.Match(i, "#if") || styler.Match(i, "#ifndef"))
if (styler.Match(i, "#ifdef") || styler.Match(i, "#if") || styler.Match(i, "#ifndef")
|| styler.Match(i, "#context_on"))
levelCurrent++;
else if (styler.Match(i, "#endif"))
else if (styler.Match(i, "#endif") || styler.Match(i, "#context_off"))
levelCurrent--;
}
}

View file

@ -12,20 +12,25 @@
#include <stdarg.h>
#include <assert.h>
#include <string>
#include <vector>
#include <map>
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
#include "StringCopy.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"
#include "SubStyles.h"
#include "DefaultLexer.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
#define HERE_DELIM_MAX 256
@ -60,7 +65,9 @@ using namespace Scintilla;
#define BASH_DELIM_STACK_MAX 7
static inline int translateBashDigit(int ch) {
namespace {
inline int translateBashDigit(int ch) {
if (ch >= '0' && ch <= '9') {
return ch - '0';
} else if (ch >= 'a' && ch <= 'z') {
@ -75,7 +82,7 @@ static inline int translateBashDigit(int ch) {
return BASH_BASE_ERROR;
}
static inline int getBashNumberBase(char *s) {
inline int getBashNumberBase(char *s) {
int i = 0;
int base = 0;
while (*s) {
@ -88,7 +95,7 @@ static inline int getBashNumberBase(char *s) {
return base;
}
static int opposite(int ch) {
int opposite(int ch) {
if (ch == '(') return ')';
if (ch == '[') return ']';
if (ch == '{') return '}';
@ -96,23 +103,200 @@ static int opposite(int ch) {
return ch;
}
static int GlobScan(StyleContext &sc) {
// forward scan for a glob-like (...), no whitespace allowed
int GlobScan(StyleContext &sc) {
// forward scan for zsh globs, disambiguate versus bash arrays
// complex expressions may still fail, e.g. unbalanced () '' "" etc
int c, sLen = 0;
int pCount = 0;
int hash = 0;
while ((c = sc.GetRelativeCharacter(++sLen)) != 0) {
if (IsASpace(c)) {
return 0;
} else if (c == '\'' || c == '\"') {
if (hash != 2) return 0;
} else if (c == '#' && hash == 0) {
hash = (sLen == 1) ? 2:1;
} else if (c == '(') {
pCount++;
} else if (c == ')') {
return sLen;
if (pCount == 0) {
if (hash) return sLen;
return 0;
}
pCount--;
}
}
return 0;
}
static void ColouriseBashDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
WordList *keywordlists[], Accessor &styler) {
bool IsCommentLine(Sci_Position line, LexAccessor &styler) {
Sci_Position pos = styler.LineStart(line);
Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
for (Sci_Position i = pos; i < eol_pos; i++) {
char ch = styler[i];
if (ch == '#')
return true;
else if (ch != ' ' && ch != '\t')
return false;
}
return false;
}
WordList &keywords = *keywordlists[0];
struct OptionsBash {
bool fold;
bool foldComment;
bool foldCompact;
OptionsBash() {
fold = false;
foldComment = false;
foldCompact = true;
}
};
const char * const bashWordListDesc[] = {
"Keywords",
0
};
struct OptionSetBash : public OptionSet<OptionsBash> {
OptionSetBash() {
DefineProperty("fold", &OptionsBash::fold);
DefineProperty("fold.comment", &OptionsBash::foldComment);
DefineProperty("fold.compact", &OptionsBash::foldCompact);
DefineWordListSets(bashWordListDesc);
}
};
const char styleSubable[] = { SCE_SH_IDENTIFIER, SCE_SH_SCALAR, 0 };
LexicalClass lexicalClasses[] = {
// Lexer Bash SCLEX_BASH SCE_SH_:
0, "SCE_SH_DEFAULT", "default", "White space",
1, "SCE_SH_ERROR", "error", "Error",
2, "SCE_SH_COMMENTLINE", "comment line", "Line comment: #",
3, "SCE_SH_NUMBER", "literal numeric", "Number",
4, "SCE_SH_WORD", "keyword", "Keyword",
5, "SCE_SH_STRING", "literal string", "String",
6, "SCE_SH_CHARACTER", "literal string", "Single quoted string",
7, "SCE_SH_OPERATOR", "operator", "Operators",
8, "SCE_SH_IDENTIFIER", "identifier", "Identifiers",
9, "SCE_SH_SCALAR", "identifier", "Scalar variable",
10, "SCE_SH_PARAM", "identifier", "Parameter",
11, "SCE_SH_BACKTICKS", "literal string", "Backtick quoted command",
12, "SCE_SH_HERE_DELIM", "operator", "Heredoc delimiter",
13, "SCE_SH_HERE_Q", "literal string", "Heredoc quoted string",
};
}
class LexerBash : public DefaultLexer {
WordList keywords;
OptionsBash options;
OptionSetBash osBash;
enum { ssIdentifier, ssScalar };
SubStyles subStyles;
public:
LexerBash() :
DefaultLexer("bash", SCLEX_BASH, lexicalClasses, ELEMENTS(lexicalClasses)),
subStyles(styleSubable, 0x80, 0x40, 0) {
}
virtual ~LexerBash() {
}
void SCI_METHOD Release() override {
delete this;
}
int SCI_METHOD Version() const override {
return lvIdentity;
}
const char * SCI_METHOD PropertyNames() override {
return osBash.PropertyNames();
}
int SCI_METHOD PropertyType(const char* name) override {
return osBash.PropertyType(name);
}
const char * SCI_METHOD DescribeProperty(const char *name) override {
return osBash.DescribeProperty(name);
}
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
const char * SCI_METHOD PropertyGet(const char* key) override {
return osBash.PropertyGet(key);
}
const char * SCI_METHOD DescribeWordListSets() override {
return osBash.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 0;
}
int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) override {
return subStyles.Allocate(styleBase, numberStyles);
}
int SCI_METHOD SubStylesStart(int styleBase) override {
return subStyles.Start(styleBase);
}
int SCI_METHOD SubStylesLength(int styleBase) override {
return subStyles.Length(styleBase);
}
int SCI_METHOD StyleFromSubStyle(int subStyle) override {
const int styleBase = subStyles.BaseStyle(subStyle);
return styleBase;
}
int SCI_METHOD PrimaryStyleFromStyle(int style) override {
return style;
}
void SCI_METHOD FreeSubStyles() override {
subStyles.Free();
}
void SCI_METHOD SetIdentifiers(int style, const char *identifiers) override {
subStyles.SetIdentifiers(style, identifiers);
}
int SCI_METHOD DistanceToSecondaryStyles() override {
return 0;
}
const char *SCI_METHOD GetSubStyleBases() override {
return styleSubable;
}
static ILexer *LexerFactoryBash() {
return new LexerBash();
}
};
Sci_Position SCI_METHOD LexerBash::PropertySet(const char *key, const char *val) {
if (osBash.PropertySet(&options, key, val)) {
return 0;
}
return -1;
}
Sci_Position SCI_METHOD LexerBash::WordListSet(int n, const char *wl) {
WordList *wordListN = 0;
switch (n) {
case 0:
wordListN = &keywords;
break;
}
Sci_Position firstModification = -1;
if (wordListN) {
WordList wlNew;
wlNew.Set(wl);
if (*wordListN != wlNew) {
wordListN->Set(wl);
firstModification = 0;
}
}
return firstModification;
}
void SCI_METHOD LexerBash::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) {
WordList cmdDelimiter, bashStruct, bashStruct_in;
cmdDelimiter.Set("| || |& & && ; ;; ( ) { }");
bashStruct.Set("if elif fi while until else then do done esac eval");
@ -226,11 +410,15 @@ static void ColouriseBashDoc(Sci_PositionU startPos, Sci_Position length, int in
};
QuoteStackCls QuoteStack;
const WordClassifier &classifierIdentifiers = subStyles.Classifier(SCE_SH_IDENTIFIER);
const WordClassifier &classifierScalars = subStyles.Classifier(SCE_SH_SCALAR);
int numBase = 0;
int digit;
Sci_PositionU endPos = startPos + length;
int cmdState = BASH_CMD_START;
int testExprType = 0;
LexAccessor styler(pAccess);
// Always backtracks to the start of a line that is not a continuation
// of the previous line (i.e. start of a bash command segment)
@ -295,6 +483,11 @@ static void ColouriseBashDoc(Sci_PositionU startPos, Sci_Position length, int in
char s[500];
char s2[10];
sc.GetCurrent(s, sizeof(s));
int identifierStyle = SCE_SH_IDENTIFIER;
int subStyle = classifierIdentifiers.ValueFor(s);
if (subStyle >= 0) {
identifierStyle = subStyle;
}
// allow keywords ending in a whitespace or command delimiter
s2[0] = static_cast<char>(sc.ch);
s2[1] = '\0';
@ -306,7 +499,7 @@ static void ColouriseBashDoc(Sci_PositionU startPos, Sci_Position length, int in
else if (strcmp(s, "do") == 0 && keywordEnds)
cmdStateNew = BASH_CMD_START;
else
sc.ChangeState(SCE_SH_IDENTIFIER);
sc.ChangeState(identifierStyle);
sc.SetState(SCE_SH_DEFAULT);
break;
}
@ -316,42 +509,49 @@ static void ColouriseBashDoc(Sci_PositionU startPos, Sci_Position length, int in
cmdStateNew = BASH_CMD_TEST;
testExprType = 0;
} else
sc.ChangeState(SCE_SH_IDENTIFIER);
sc.ChangeState(identifierStyle);
}
// detect bash construct keywords
else if (bashStruct.InList(s)) {
if (cmdState == BASH_CMD_START && keywordEnds)
cmdStateNew = BASH_CMD_START;
else
sc.ChangeState(SCE_SH_IDENTIFIER);
sc.ChangeState(identifierStyle);
}
// 'for'|'case'|'select' needs 'in'|'do' to be highlighted later
else if (bashStruct_in.InList(s)) {
if (cmdState == BASH_CMD_START && keywordEnds)
cmdStateNew = BASH_CMD_WORD;
else
sc.ChangeState(SCE_SH_IDENTIFIER);
sc.ChangeState(identifierStyle);
}
// disambiguate option items and file test operators
else if (s[0] == '-') {
if (cmdState != BASH_CMD_TEST)
sc.ChangeState(SCE_SH_IDENTIFIER);
sc.ChangeState(identifierStyle);
}
// disambiguate keywords and identifiers
else if (cmdState != BASH_CMD_START
|| !(keywords.InList(s) && keywordEnds)) {
sc.ChangeState(SCE_SH_IDENTIFIER);
sc.ChangeState(identifierStyle);
}
sc.SetState(SCE_SH_DEFAULT);
}
break;
case SCE_SH_IDENTIFIER:
if (sc.chPrev == '\\') { // for escaped chars
sc.ForwardSetState(SCE_SH_DEFAULT);
} else if (!setWord.Contains(sc.ch)) {
sc.SetState(SCE_SH_DEFAULT);
} else if (cmdState == BASH_CMD_ARITH && !setWordStart.Contains(sc.ch)) {
sc.SetState(SCE_SH_DEFAULT);
if (sc.chPrev == '\\' || !setWord.Contains(sc.ch) ||
(cmdState == BASH_CMD_ARITH && !setWordStart.Contains(sc.ch))) {
char s[500];
sc.GetCurrent(s, sizeof(s));
int subStyle = classifierIdentifiers.ValueFor(s);
if (subStyle >= 0) {
sc.ChangeState(subStyle);
}
if (sc.chPrev == '\\') { // for escaped chars
sc.ForwardSetState(SCE_SH_DEFAULT);
} else {
sc.SetState(SCE_SH_DEFAULT);
}
}
break;
case SCE_SH_NUMBER:
@ -505,6 +705,12 @@ static void ColouriseBashDoc(Sci_PositionU startPos, Sci_Position length, int in
break;
case SCE_SH_SCALAR: // variable names
if (!setParam.Contains(sc.ch)) {
char s[500];
sc.GetCurrent(s, sizeof(s));
int subStyle = classifierScalars.ValueFor(&s[1]); // skip the $
if (subStyle >= 0) {
sc.ChangeState(subStyle);
}
if (sc.LengthCurrent() == 1) {
// Special variable: $(, $_ etc.
sc.ForwardSetState(SCE_SH_DEFAULT);
@ -788,23 +994,12 @@ static void ColouriseBashDoc(Sci_PositionU startPos, Sci_Position length, int in
sc.Complete();
}
static bool IsCommentLine(Sci_Position line, Accessor &styler) {
Sci_Position pos = styler.LineStart(line);
Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
for (Sci_Position i = pos; i < eol_pos; i++) {
char ch = styler[i];
if (ch == '#')
return true;
else if (ch != ' ' && ch != '\t')
return false;
}
return false;
}
void SCI_METHOD LexerBash::Fold(Sci_PositionU startPos, Sci_Position length, int, IDocument *pAccess) {
if(!options.fold)
return;
LexAccessor styler(pAccess);
static void FoldBashDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[],
Accessor &styler) {
bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
Sci_PositionU endPos = startPos + length;
int visibleChars = 0;
int skipHereCh = 0;
@ -813,6 +1008,8 @@ static void FoldBashDoc(Sci_PositionU startPos, Sci_Position length, int, WordLi
int levelCurrent = levelPrev;
char chNext = styler[startPos];
int styleNext = styler.StyleAt(startPos);
char word[8] = { '\0' }; // we're not interested in long words anyway
unsigned int wordlen = 0;
for (Sci_PositionU i = startPos; i < endPos; i++) {
char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
@ -820,7 +1017,7 @@ static void FoldBashDoc(Sci_PositionU startPos, Sci_Position length, int, WordLi
styleNext = styler.StyleAt(i + 1);
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
// Comment folding
if (foldComment && atEOL && IsCommentLine(lineCurrent, styler))
if (options.foldComment && atEOL && IsCommentLine(lineCurrent, styler))
{
if (!IsCommentLine(lineCurrent - 1, styler)
&& IsCommentLine(lineCurrent + 1, styler))
@ -829,6 +1026,19 @@ static void FoldBashDoc(Sci_PositionU startPos, Sci_Position length, int, WordLi
&& !IsCommentLine(lineCurrent + 1, styler))
levelCurrent--;
}
if (style == SCE_SH_WORD) {
if ((wordlen + 1) < sizeof(word))
word[wordlen++] = ch;
if (styleNext != style) {
word[wordlen] = '\0';
wordlen = 0;
if (strcmp(word, "if") == 0 || strcmp(word, "case") == 0 || strcmp(word, "do") == 0) {
levelCurrent++;
} else if (strcmp(word, "fi") == 0 || strcmp(word, "esac") == 0 || strcmp(word, "done") == 0) {
levelCurrent--;
}
}
}
if (style == SCE_SH_OPERATOR) {
if (ch == '{') {
levelCurrent++;
@ -854,7 +1064,7 @@ static void FoldBashDoc(Sci_PositionU startPos, Sci_Position length, int, WordLi
}
if (atEOL) {
int lev = levelPrev;
if (visibleChars == 0 && foldCompact)
if (visibleChars == 0 && options.foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG;
if ((levelCurrent > levelPrev) && (visibleChars > 0))
lev |= SC_FOLDLEVELHEADERFLAG;
@ -873,9 +1083,4 @@ static void FoldBashDoc(Sci_PositionU startPos, Sci_Position length, int, WordLi
styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}
static const char * const bashWordListDesc[] = {
"Keywords",
0
};
LexerModule lmBash(SCLEX_BASH, ColouriseBashDoc, "bash", FoldBashDoc, bashWordListDesc);
LexerModule lmBash(SCLEX_BASH, LexerBash::LexerFactoryBash, "bash", bashWordListDesc);

View file

@ -37,10 +37,9 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"
#include "DefaultLexer.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
/* Bits:
* 1 - whitespace
@ -226,54 +225,59 @@ struct OptionSetBasic : public OptionSet<OptionsBasic> {
}
};
class LexerBasic : public ILexer {
class LexerBasic : public DefaultLexer {
char comment_char;
int (*CheckFoldPoint)(char const *, int &);
WordList keywordlists[4];
OptionsBasic options;
OptionSetBasic osBasic;
public:
LexerBasic(char comment_char_, int (*CheckFoldPoint_)(char const *, int &), const char * const wordListDescriptions[]) :
LexerBasic(const char *languageName_, int language_, char comment_char_,
int (*CheckFoldPoint_)(char const *, int &), const char * const wordListDescriptions[]) :
DefaultLexer(languageName_, language_),
comment_char(comment_char_),
CheckFoldPoint(CheckFoldPoint_),
osBasic(wordListDescriptions) {
}
virtual ~LexerBasic() {
}
void SCI_METHOD Release() {
void SCI_METHOD Release() override {
delete this;
}
int SCI_METHOD Version() const {
return lvOriginal;
int SCI_METHOD Version() const override {
return lvIdentity;
}
const char * SCI_METHOD PropertyNames() {
const char * SCI_METHOD PropertyNames() override {
return osBasic.PropertyNames();
}
int SCI_METHOD PropertyType(const char *name) {
int SCI_METHOD PropertyType(const char *name) override {
return osBasic.PropertyType(name);
}
const char * SCI_METHOD DescribeProperty(const char *name) {
const char * SCI_METHOD DescribeProperty(const char *name) override {
return osBasic.DescribeProperty(name);
}
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val);
const char * SCI_METHOD DescribeWordListSets() {
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
const char * SCI_METHOD PropertyGet(const char *key) override {
return osBasic.PropertyGet(key);
}
const char * SCI_METHOD DescribeWordListSets() override {
return osBasic.DescribeWordListSets();
}
Sci_Position SCI_METHOD WordListSet(int n, const char *wl);
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess);
void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess);
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 *) {
void * SCI_METHOD PrivateCall(int, void *) override {
return 0;
}
static ILexer *LexerFactoryBlitzBasic() {
return new LexerBasic(';', CheckBlitzFoldPoint, blitzbasicWordListDesc);
return new LexerBasic("blitzbasic", SCLEX_BLITZBASIC, ';', CheckBlitzFoldPoint, blitzbasicWordListDesc);
}
static ILexer *LexerFactoryPureBasic() {
return new LexerBasic(';', CheckPureFoldPoint, purebasicWordListDesc);
return new LexerBasic("purebasic", SCLEX_PUREBASIC, ';', CheckPureFoldPoint, purebasicWordListDesc);
}
static ILexer *LexerFactoryFreeBasic() {
return new LexerBasic('\'', CheckFreeFoldPoint, freebasicWordListDesc );
return new LexerBasic("freebasic", SCLEX_FREEBASIC, '\'', CheckFreeFoldPoint, freebasicWordListDesc );
}
};

View file

@ -23,9 +23,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static bool Is0To9(char ch) {
return (ch >= '0') && (ch <= '9');
@ -43,7 +41,8 @@ static inline bool AtEOL(Accessor &styler, Sci_PositionU i) {
// Tests for BATCH Operators
static bool IsBOperator(char ch) {
return (ch == '=') || (ch == '+') || (ch == '>') || (ch == '<') ||
(ch == '|') || (ch == '?') || (ch == '*');
(ch == '|') || (ch == '?') || (ch == '*')||
(ch == '&') || (ch == '(') || (ch == ')');
}
// Tests for BATCH Separators
@ -52,413 +51,35 @@ static bool IsBSeparator(char ch) {
(ch == '\"') || (ch == '\'') || (ch == '/');
}
static void ColouriseBatchLine(
char *lineBuffer,
Sci_PositionU lengthLine,
Sci_PositionU startLine,
Sci_PositionU endPos,
WordList *keywordlists[],
Accessor &styler) {
Sci_PositionU offset = 0; // Line Buffer Offset
Sci_PositionU cmdLoc; // External Command / Program Location
char wordBuffer[81]; // Word Buffer - large to catch long paths
Sci_PositionU wbl; // Word Buffer Length
Sci_PositionU wbo; // Word Buffer Offset - also Special Keyword Buffer Length
WordList &keywords = *keywordlists[0]; // Internal Commands
WordList &keywords2 = *keywordlists[1]; // External Commands (optional)
// CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords
// Toggling Regular Keyword Checking off improves readability
// Other Regular Keywords and External Commands / Programs might also benefit from toggling
// Need a more robust algorithm to properly toggle Regular Keyword Checking
bool continueProcessing = true; // Used to toggle Regular Keyword Checking
// Special Keywords are those that allow certain characters without whitespace after the command
// Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path=
// Special Keyword Buffer used to determine if the first n characters is a Keyword
char sKeywordBuffer[10]; // Special Keyword Buffer
bool sKeywordFound; // Exit Special Keyword for-loop if found
// Skip initial spaces
while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
offset++;
// Tests for escape character
static bool IsEscaped(char* wordStr, Sci_PositionU pos) {
bool isQoted=false;
while (pos>0){
pos--;
if (wordStr[pos]=='^')
isQoted=!isQoted;
else
break;
}
// Colorize Default Text
styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
// Set External Command / Program Location
cmdLoc = offset;
return isQoted;
}
// Check for Fake Label (Comment) or Real Label - return if found
if (lineBuffer[offset] == ':') {
if (lineBuffer[offset + 1] == ':') {
// Colorize Fake Label (Comment) - :: is similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm
styler.ColourTo(endPos, SCE_BAT_COMMENT);
} else {
// Colorize Real Label
styler.ColourTo(endPos, SCE_BAT_LABEL);
// Tests for quote character
static bool textQuoted(char *lineBuffer, Sci_PositionU endPos) {
char strBuffer[1024];
strncpy(strBuffer, lineBuffer, endPos);
strBuffer[endPos] = '\0';
char *pQuote;
pQuote = strchr(strBuffer, '"');
bool CurrentStatus = false;
while (pQuote != NULL)
{
if (!IsEscaped(strBuffer, pQuote - strBuffer)) {
CurrentStatus = !CurrentStatus;
}
return;
// Check for Drive Change (Drive Change is internal command) - return if found
} else if ((IsAlphabetic(lineBuffer[offset])) &&
(lineBuffer[offset + 1] == ':') &&
((isspacechar(lineBuffer[offset + 2])) ||
(((lineBuffer[offset + 2] == '\\')) &&
(isspacechar(lineBuffer[offset + 3]))))) {
// Colorize Regular Keyword
styler.ColourTo(endPos, SCE_BAT_WORD);
return;
pQuote = strchr(pQuote + 1, '"');
}
// Check for Hide Command (@ECHO OFF/ON)
if (lineBuffer[offset] == '@') {
styler.ColourTo(startLine + offset, SCE_BAT_HIDE);
offset++;
}
// Skip next spaces
while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
offset++;
}
// Read remainder of line word-at-a-time or remainder-of-word-at-a-time
while (offset < lengthLine) {
if (offset > startLine) {
// Colorize Default Text
styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
}
// Copy word from Line Buffer into Word Buffer
wbl = 0;
for (; offset < lengthLine && wbl < 80 &&
!isspacechar(lineBuffer[offset]); wbl++, offset++) {
wordBuffer[wbl] = static_cast<char>(tolower(lineBuffer[offset]));
}
wordBuffer[wbl] = '\0';
wbo = 0;
// Check for Comment - return if found
if (CompareCaseInsensitive(wordBuffer, "rem") == 0) {
styler.ColourTo(endPos, SCE_BAT_COMMENT);
return;
}
// Check for Separator
if (IsBSeparator(wordBuffer[0])) {
// Check for External Command / Program
if ((cmdLoc == offset - wbl) &&
((wordBuffer[0] == ':') ||
(wordBuffer[0] == '\\') ||
(wordBuffer[0] == '.'))) {
// Reset Offset to re-process remainder of word
offset -= (wbl - 1);
// Colorize External Command / Program
if (!keywords2) {
styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
} else if (keywords2.InList(wordBuffer)) {
styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
} else {
styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
}
// Reset External Command / Program Location
cmdLoc = offset;
} else {
// Reset Offset to re-process remainder of word
offset -= (wbl - 1);
// Colorize Default Text
styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
}
// Check for Regular Keyword in list
} else if ((keywords.InList(wordBuffer)) &&
(continueProcessing)) {
// ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking
if ((CompareCaseInsensitive(wordBuffer, "echo") == 0) ||
(CompareCaseInsensitive(wordBuffer, "goto") == 0) ||
(CompareCaseInsensitive(wordBuffer, "prompt") == 0) ||
(CompareCaseInsensitive(wordBuffer, "set") == 0)) {
continueProcessing = false;
}
// Identify External Command / Program Location for ERRORLEVEL, and EXIST
if ((CompareCaseInsensitive(wordBuffer, "errorlevel") == 0) ||
(CompareCaseInsensitive(wordBuffer, "exist") == 0)) {
// Reset External Command / Program Location
cmdLoc = offset;
// Skip next spaces
while ((cmdLoc < lengthLine) &&
(isspacechar(lineBuffer[cmdLoc]))) {
cmdLoc++;
}
// Skip comparison
while ((cmdLoc < lengthLine) &&
(!isspacechar(lineBuffer[cmdLoc]))) {
cmdLoc++;
}
// Skip next spaces
while ((cmdLoc < lengthLine) &&
(isspacechar(lineBuffer[cmdLoc]))) {
cmdLoc++;
}
// Identify External Command / Program Location for CALL, DO, LOADHIGH and LH
} else if ((CompareCaseInsensitive(wordBuffer, "call") == 0) ||
(CompareCaseInsensitive(wordBuffer, "do") == 0) ||
(CompareCaseInsensitive(wordBuffer, "loadhigh") == 0) ||
(CompareCaseInsensitive(wordBuffer, "lh") == 0)) {
// Reset External Command / Program Location
cmdLoc = offset;
// Skip next spaces
while ((cmdLoc < lengthLine) &&
(isspacechar(lineBuffer[cmdLoc]))) {
cmdLoc++;
}
}
// Colorize Regular keyword
styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD);
// No need to Reset Offset
// Check for Special Keyword in list, External Command / Program, or Default Text
} else if ((wordBuffer[0] != '%') &&
(wordBuffer[0] != '!') &&
(!IsBOperator(wordBuffer[0])) &&
(continueProcessing)) {
// Check for Special Keyword
// Affected Commands are in Length range 2-6
// Good that ERRORLEVEL, EXIST, CALL, DO, LOADHIGH, and LH are unaffected
sKeywordFound = false;
for (Sci_PositionU keywordLength = 2; keywordLength < wbl && keywordLength < 7 && !sKeywordFound; keywordLength++) {
wbo = 0;
// Copy Keyword Length from Word Buffer into Special Keyword Buffer
for (; wbo < keywordLength; wbo++) {
sKeywordBuffer[wbo] = static_cast<char>(wordBuffer[wbo]);
}
sKeywordBuffer[wbo] = '\0';
// Check for Special Keyword in list
if ((keywords.InList(sKeywordBuffer)) &&
((IsBOperator(wordBuffer[wbo])) ||
(IsBSeparator(wordBuffer[wbo])))) {
sKeywordFound = true;
// ECHO requires no further Regular Keyword Checking
if (CompareCaseInsensitive(sKeywordBuffer, "echo") == 0) {
continueProcessing = false;
}
// Colorize Special Keyword as Regular Keyword
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_WORD);
// Reset Offset to re-process remainder of word
offset -= (wbl - wbo);
}
}
// Check for External Command / Program or Default Text
if (!sKeywordFound) {
wbo = 0;
// Check for External Command / Program
if (cmdLoc == offset - wbl) {
// Read up to %, Operator or Separator
while ((wbo < wbl) &&
(wordBuffer[wbo] != '%') &&
(wordBuffer[wbo] != '!') &&
(!IsBOperator(wordBuffer[wbo])) &&
(!IsBSeparator(wordBuffer[wbo]))) {
wbo++;
}
// Reset External Command / Program Location
cmdLoc = offset - (wbl - wbo);
// Reset Offset to re-process remainder of word
offset -= (wbl - wbo);
// CHOICE requires no further Regular Keyword Checking
if (CompareCaseInsensitive(wordBuffer, "choice") == 0) {
continueProcessing = false;
}
// Check for START (and its switches) - What follows is External Command \ Program
if (CompareCaseInsensitive(wordBuffer, "start") == 0) {
// Reset External Command / Program Location
cmdLoc = offset;
// Skip next spaces
while ((cmdLoc < lengthLine) &&
(isspacechar(lineBuffer[cmdLoc]))) {
cmdLoc++;
}
// Reset External Command / Program Location if command switch detected
if (lineBuffer[cmdLoc] == '/') {
// Skip command switch
while ((cmdLoc < lengthLine) &&
(!isspacechar(lineBuffer[cmdLoc]))) {
cmdLoc++;
}
// Skip next spaces
while ((cmdLoc < lengthLine) &&
(isspacechar(lineBuffer[cmdLoc]))) {
cmdLoc++;
}
}
}
// Colorize External Command / Program
if (!keywords2) {
styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
} else if (keywords2.InList(wordBuffer)) {
styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
} else {
styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
}
// No need to Reset Offset
// Check for Default Text
} else {
// Read up to %, Operator or Separator
while ((wbo < wbl) &&
(wordBuffer[wbo] != '%') &&
(wordBuffer[wbo] != '!') &&
(!IsBOperator(wordBuffer[wbo])) &&
(!IsBSeparator(wordBuffer[wbo]))) {
wbo++;
}
// Colorize Default Text
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT);
// Reset Offset to re-process remainder of word
offset -= (wbl - wbo);
}
}
// Check for Argument (%n), Environment Variable (%x...%) or Local Variable (%%a)
} else if (wordBuffer[0] == '%') {
// Colorize Default Text
styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT);
wbo++;
// Search to end of word for second % (can be a long path)
while ((wbo < wbl) &&
(wordBuffer[wbo] != '%') &&
(!IsBOperator(wordBuffer[wbo])) &&
(!IsBSeparator(wordBuffer[wbo]))) {
wbo++;
}
// Check for Argument (%n) or (%*)
if (((Is0To9(wordBuffer[1])) || (wordBuffer[1] == '*')) &&
(wordBuffer[wbo] != '%')) {
// Check for External Command / Program
if (cmdLoc == offset - wbl) {
cmdLoc = offset - (wbl - 2);
}
// Colorize Argument
styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_IDENTIFIER);
// Reset Offset to re-process remainder of word
offset -= (wbl - 2);
// Check for Expanded Argument (%~...) / Variable (%%~...)
} else if (((wbl > 1) && (wordBuffer[1] == '~')) ||
((wbl > 2) && (wordBuffer[1] == '%') && (wordBuffer[2] == '~'))) {
// Check for External Command / Program
if (cmdLoc == offset - wbl) {
cmdLoc = offset - (wbl - wbo);
}
// Colorize Expanded Argument / Variable
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER);
// Reset Offset to re-process remainder of word
offset -= (wbl - wbo);
// Check for Environment Variable (%x...%)
} else if ((wordBuffer[1] != '%') &&
(wordBuffer[wbo] == '%')) {
wbo++;
// Check for External Command / Program
if (cmdLoc == offset - wbl) {
cmdLoc = offset - (wbl - wbo);
}
// Colorize Environment Variable
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER);
// Reset Offset to re-process remainder of word
offset -= (wbl - wbo);
// Check for Local Variable (%%a)
} else if (
(wbl > 2) &&
(wordBuffer[1] == '%') &&
(wordBuffer[2] != '%') &&
(!IsBOperator(wordBuffer[2])) &&
(!IsBSeparator(wordBuffer[2]))) {
// Check for External Command / Program
if (cmdLoc == offset - wbl) {
cmdLoc = offset - (wbl - 3);
}
// Colorize Local Variable
styler.ColourTo(startLine + offset - 1 - (wbl - 3), SCE_BAT_IDENTIFIER);
// Reset Offset to re-process remainder of word
offset -= (wbl - 3);
}
// Check for Environment Variable (!x...!)
} else if (wordBuffer[0] == '!') {
// Colorize Default Text
styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT);
wbo++;
// Search to end of word for second ! (can be a long path)
while ((wbo < wbl) &&
(wordBuffer[wbo] != '!') &&
(!IsBOperator(wordBuffer[wbo])) &&
(!IsBSeparator(wordBuffer[wbo]))) {
wbo++;
}
if (wordBuffer[wbo] == '!') {
wbo++;
// Check for External Command / Program
if (cmdLoc == offset - wbl) {
cmdLoc = offset - (wbl - wbo);
}
// Colorize Environment Variable
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER);
// Reset Offset to re-process remainder of word
offset -= (wbl - wbo);
}
// Check for Operator
} else if (IsBOperator(wordBuffer[0])) {
// Colorize Default Text
styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT);
// Check for Comparison Operator
if ((wordBuffer[0] == '=') && (wordBuffer[1] == '=')) {
// Identify External Command / Program Location for IF
cmdLoc = offset;
// Skip next spaces
while ((cmdLoc < lengthLine) &&
(isspacechar(lineBuffer[cmdLoc]))) {
cmdLoc++;
}
// Colorize Comparison Operator
styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_OPERATOR);
// Reset Offset to re-process remainder of word
offset -= (wbl - 2);
// Check for Pipe Operator
} else if (wordBuffer[0] == '|') {
// Reset External Command / Program Location
cmdLoc = offset - wbl + 1;
// Skip next spaces
while ((cmdLoc < lengthLine) &&
(isspacechar(lineBuffer[cmdLoc]))) {
cmdLoc++;
}
// Colorize Pipe Operator
styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR);
// Reset Offset to re-process remainder of word
offset -= (wbl - 1);
// Check for Other Operator
} else {
// Check for > Operator
if (wordBuffer[0] == '>') {
// Turn Keyword and External Command / Program checking back on
continueProcessing = true;
}
// Colorize Other Operator
styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR);
// Reset Offset to re-process remainder of word
offset -= (wbl - 1);
}
// Check for Default Text
} else {
// Read up to %, Operator or Separator
while ((wbo < wbl) &&
(wordBuffer[wbo] != '%') &&
(wordBuffer[wbo] != '!') &&
(!IsBOperator(wordBuffer[wbo])) &&
(!IsBSeparator(wordBuffer[wbo]))) {
wbo++;
}
// Colorize Default Text
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT);
// Reset Offset to re-process remainder of word
offset -= (wbl - wbo);
}
// Skip next spaces - nothing happens if Offset was Reset
while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
offset++;
}
}
// Colorize Default Text for remainder of line - currently not lexed
styler.ColourTo(endPos, SCE_BAT_DEFAULT);
return CurrentStatus;
}
static void ColouriseBatchDoc(
@ -467,6 +88,23 @@ static void ColouriseBatchDoc(
int /*initStyle*/,
WordList *keywordlists[],
Accessor &styler) {
// Always backtracks to the start of a line that is not a continuation
// of the previous line
if (startPos > 0) {
Sci_Position ln = styler.GetLine(startPos); // Current line number
while (startPos > 0) {
ln--;
if ((styler.SafeGetCharAt(startPos-3) == '^' && styler.SafeGetCharAt(startPos-2) == '\r' && styler.SafeGetCharAt(startPos-1) == '\n')
|| styler.SafeGetCharAt(startPos-2) == '^') { // handle '^' line continuation
// When the line continuation is found,
// set the Start Position to the Start of the previous line
length+=startPos-styler.LineStart(ln);
startPos=styler.LineStart(ln);
}
else
break;
}
}
char lineBuffer[1024];
@ -474,21 +112,459 @@ static void ColouriseBatchDoc(
styler.StartSegment(startPos);
Sci_PositionU linePos = 0;
Sci_PositionU startLine = startPos;
bool continueProcessing = true; // Used to toggle Regular Keyword Checking
bool isNotAssigned=false; // Used to flag Assignment in Set operation
for (Sci_PositionU i = startPos; i < startPos + length; i++) {
lineBuffer[linePos++] = styler[i];
if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
// End of line (or of line buffer) met, colourise it
if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1) || (i==startPos + length-1)) {
// End of line (or of line buffer) (or End of Last Line) met, colourise it
lineBuffer[linePos] = '\0';
ColouriseBatchLine(lineBuffer, linePos, startLine, i, keywordlists, styler);
Sci_PositionU lengthLine=linePos;
Sci_PositionU endPos=i;
Sci_PositionU offset = 0; // Line Buffer Offset
Sci_PositionU cmdLoc; // External Command / Program Location
char wordBuffer[81]; // Word Buffer - large to catch long paths
Sci_PositionU wbl; // Word Buffer Length
Sci_PositionU wbo; // Word Buffer Offset - also Special Keyword Buffer Length
WordList &keywords = *keywordlists[0]; // Internal Commands
WordList &keywords2 = *keywordlists[1]; // External Commands (optional)
// CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords
// Toggling Regular Keyword Checking off improves readability
// Other Regular Keywords and External Commands / Programs might also benefit from toggling
// Need a more robust algorithm to properly toggle Regular Keyword Checking
bool stopLineProcessing=false; // Used to stop line processing if Comment or Drive Change found
// Special Keywords are those that allow certain characters without whitespace after the command
// Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path=
// Special Keyword Buffer used to determine if the first n characters is a Keyword
char sKeywordBuffer[10]; // Special Keyword Buffer
bool sKeywordFound; // Exit Special Keyword for-loop if found
// Skip initial spaces
while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
offset++;
}
// Colorize Default Text
styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
// Set External Command / Program Location
cmdLoc = offset;
// Check for Fake Label (Comment) or Real Label - return if found
if (lineBuffer[offset] == ':') {
if (lineBuffer[offset + 1] == ':') {
// Colorize Fake Label (Comment) - :: is similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm
styler.ColourTo(endPos, SCE_BAT_COMMENT);
} else {
// Colorize Real Label
styler.ColourTo(endPos, SCE_BAT_LABEL);
}
stopLineProcessing=true;
// Check for Drive Change (Drive Change is internal command) - return if found
} else if ((IsAlphabetic(lineBuffer[offset])) &&
(lineBuffer[offset + 1] == ':') &&
((isspacechar(lineBuffer[offset + 2])) ||
(((lineBuffer[offset + 2] == '\\')) &&
(isspacechar(lineBuffer[offset + 3]))))) {
// Colorize Regular Keyword
styler.ColourTo(endPos, SCE_BAT_WORD);
stopLineProcessing=true;
}
// Check for Hide Command (@ECHO OFF/ON)
if (lineBuffer[offset] == '@') {
styler.ColourTo(startLine + offset, SCE_BAT_HIDE);
offset++;
}
// Skip next spaces
while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
offset++;
}
// Read remainder of line word-at-a-time or remainder-of-word-at-a-time
while (offset < lengthLine && !stopLineProcessing) {
if (offset > startLine) {
// Colorize Default Text
styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
}
// Copy word from Line Buffer into Word Buffer
wbl = 0;
for (; offset < lengthLine && wbl < 80 &&
!isspacechar(lineBuffer[offset]); wbl++, offset++) {
wordBuffer[wbl] = static_cast<char>(tolower(lineBuffer[offset]));
}
wordBuffer[wbl] = '\0';
wbo = 0;
// Check for Comment - return if found
if ((CompareCaseInsensitive(wordBuffer, "rem") == 0) && continueProcessing) {
styler.ColourTo(endPos, SCE_BAT_COMMENT);
break;
}
// Check for Separator
if (IsBSeparator(wordBuffer[0])) {
// Check for External Command / Program
if ((cmdLoc == offset - wbl) &&
((wordBuffer[0] == ':') ||
(wordBuffer[0] == '\\') ||
(wordBuffer[0] == '.'))) {
// Reset Offset to re-process remainder of word
offset -= (wbl - 1);
// Colorize External Command / Program
if (!keywords2) {
styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
} else if (keywords2.InList(wordBuffer)) {
styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
} else {
styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
}
// Reset External Command / Program Location
cmdLoc = offset;
} else {
// Reset Offset to re-process remainder of word
offset -= (wbl - 1);
// Colorize Default Text
styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
}
// Check for Regular Keyword in list
} else if ((keywords.InList(wordBuffer)) &&
(continueProcessing)) {
// ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking
if ((CompareCaseInsensitive(wordBuffer, "echo") == 0) ||
(CompareCaseInsensitive(wordBuffer, "goto") == 0) ||
(CompareCaseInsensitive(wordBuffer, "prompt") == 0)) {
continueProcessing = false;
}
// SET requires additional processing for the assignment operator
if (CompareCaseInsensitive(wordBuffer, "set") == 0) {
continueProcessing = false;
isNotAssigned=true;
}
// Identify External Command / Program Location for ERRORLEVEL, and EXIST
if ((CompareCaseInsensitive(wordBuffer, "errorlevel") == 0) ||
(CompareCaseInsensitive(wordBuffer, "exist") == 0)) {
// Reset External Command / Program Location
cmdLoc = offset;
// Skip next spaces
while ((cmdLoc < lengthLine) &&
(isspacechar(lineBuffer[cmdLoc]))) {
cmdLoc++;
}
// Skip comparison
while ((cmdLoc < lengthLine) &&
(!isspacechar(lineBuffer[cmdLoc]))) {
cmdLoc++;
}
// Skip next spaces
while ((cmdLoc < lengthLine) &&
(isspacechar(lineBuffer[cmdLoc]))) {
cmdLoc++;
}
// Identify External Command / Program Location for CALL, DO, LOADHIGH and LH
} else if ((CompareCaseInsensitive(wordBuffer, "call") == 0) ||
(CompareCaseInsensitive(wordBuffer, "do") == 0) ||
(CompareCaseInsensitive(wordBuffer, "loadhigh") == 0) ||
(CompareCaseInsensitive(wordBuffer, "lh") == 0)) {
// Reset External Command / Program Location
cmdLoc = offset;
// Skip next spaces
while ((cmdLoc < lengthLine) &&
(isspacechar(lineBuffer[cmdLoc]))) {
cmdLoc++;
}
}
// Colorize Regular keyword
styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD);
// No need to Reset Offset
// Check for Special Keyword in list, External Command / Program, or Default Text
} else if ((wordBuffer[0] != '%') &&
(wordBuffer[0] != '!') &&
(!IsBOperator(wordBuffer[0])) &&
(continueProcessing)) {
// Check for Special Keyword
// Affected Commands are in Length range 2-6
// Good that ERRORLEVEL, EXIST, CALL, DO, LOADHIGH, and LH are unaffected
sKeywordFound = false;
for (Sci_PositionU keywordLength = 2; keywordLength < wbl && keywordLength < 7 && !sKeywordFound; keywordLength++) {
wbo = 0;
// Copy Keyword Length from Word Buffer into Special Keyword Buffer
for (; wbo < keywordLength; wbo++) {
sKeywordBuffer[wbo] = static_cast<char>(wordBuffer[wbo]);
}
sKeywordBuffer[wbo] = '\0';
// Check for Special Keyword in list
if ((keywords.InList(sKeywordBuffer)) &&
((IsBOperator(wordBuffer[wbo])) ||
(IsBSeparator(wordBuffer[wbo])))) {
sKeywordFound = true;
// ECHO requires no further Regular Keyword Checking
if (CompareCaseInsensitive(sKeywordBuffer, "echo") == 0) {
continueProcessing = false;
}
// Colorize Special Keyword as Regular Keyword
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_WORD);
// Reset Offset to re-process remainder of word
offset -= (wbl - wbo);
}
}
// Check for External Command / Program or Default Text
if (!sKeywordFound) {
wbo = 0;
// Check for External Command / Program
if (cmdLoc == offset - wbl) {
// Read up to %, Operator or Separator
while ((wbo < wbl) &&
(((wordBuffer[wbo] != '%') &&
(wordBuffer[wbo] != '!') &&
(!IsBOperator(wordBuffer[wbo])) &&
(!IsBSeparator(wordBuffer[wbo]))))) {
wbo++;
}
// Reset External Command / Program Location
cmdLoc = offset - (wbl - wbo);
// Reset Offset to re-process remainder of word
offset -= (wbl - wbo);
// CHOICE requires no further Regular Keyword Checking
if (CompareCaseInsensitive(wordBuffer, "choice") == 0) {
continueProcessing = false;
}
// Check for START (and its switches) - What follows is External Command \ Program
if (CompareCaseInsensitive(wordBuffer, "start") == 0) {
// Reset External Command / Program Location
cmdLoc = offset;
// Skip next spaces
while ((cmdLoc < lengthLine) &&
(isspacechar(lineBuffer[cmdLoc]))) {
cmdLoc++;
}
// Reset External Command / Program Location if command switch detected
if (lineBuffer[cmdLoc] == '/') {
// Skip command switch
while ((cmdLoc < lengthLine) &&
(!isspacechar(lineBuffer[cmdLoc]))) {
cmdLoc++;
}
// Skip next spaces
while ((cmdLoc < lengthLine) &&
(isspacechar(lineBuffer[cmdLoc]))) {
cmdLoc++;
}
}
}
// Colorize External Command / Program
if (!keywords2) {
styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
} else if (keywords2.InList(wordBuffer)) {
styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
} else {
styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
}
// No need to Reset Offset
// Check for Default Text
} else {
// Read up to %, Operator or Separator
while ((wbo < wbl) &&
(((wordBuffer[wbo] != '%') &&
(wordBuffer[wbo] != '!') &&
(!IsBOperator(wordBuffer[wbo])) &&
(!IsBSeparator(wordBuffer[wbo]))))) {
wbo++;
}
// Colorize Default Text
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT);
// Reset Offset to re-process remainder of word
offset -= (wbl - wbo);
}
}
// Check for Argument (%n), Environment Variable (%x...%) or Local Variable (%%a)
} else if (wordBuffer[0] == '%') {
// Colorize Default Text
styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT);
wbo++;
// Search to end of word for second % (can be a long path)
while ((wbo < wbl) &&
(wordBuffer[wbo] != '%')) {
wbo++;
}
// Check for Argument (%n) or (%*)
if (((Is0To9(wordBuffer[1])) || (wordBuffer[1] == '*')) &&
(wordBuffer[wbo] != '%')) {
// Check for External Command / Program
if (cmdLoc == offset - wbl) {
cmdLoc = offset - (wbl - 2);
}
// Colorize Argument
styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_IDENTIFIER);
// Reset Offset to re-process remainder of word
offset -= (wbl - 2);
// Check for Expanded Argument (%~...) / Variable (%%~...)
} else if (((wbl > 1) && (wordBuffer[1] == '~')) ||
((wbl > 2) && (wordBuffer[1] == '%') && (wordBuffer[2] == '~'))) {
// Check for External Command / Program
if (cmdLoc == offset - wbl) {
cmdLoc = offset - (wbl - wbo);
}
// Colorize Expanded Argument / Variable
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER);
// Reset Offset to re-process remainder of word
offset -= (wbl - wbo);
// Check for Environment Variable (%x...%)
} else if ((wordBuffer[1] != '%') &&
(wordBuffer[wbo] == '%')) {
wbo++;
// Check for External Command / Program
if (cmdLoc == offset - wbl) {
cmdLoc = offset - (wbl - wbo);
}
// Colorize Environment Variable
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER);
// Reset Offset to re-process remainder of word
offset -= (wbl - wbo);
// Check for Local Variable (%%a)
} else if (
(wbl > 2) &&
(wordBuffer[1] == '%') &&
(wordBuffer[2] != '%') &&
(!IsBOperator(wordBuffer[2])) &&
(!IsBSeparator(wordBuffer[2]))) {
// Check for External Command / Program
if (cmdLoc == offset - wbl) {
cmdLoc = offset - (wbl - 3);
}
// Colorize Local Variable
styler.ColourTo(startLine + offset - 1 - (wbl - 3), SCE_BAT_IDENTIFIER);
// Reset Offset to re-process remainder of word
offset -= (wbl - 3);
}
// Check for Environment Variable (!x...!)
} else if (wordBuffer[0] == '!') {
// Colorize Default Text
styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT);
wbo++;
// Search to end of word for second ! (can be a long path)
while ((wbo < wbl) &&
(wordBuffer[wbo] != '!')) {
wbo++;
}
if (wordBuffer[wbo] == '!') {
wbo++;
// Check for External Command / Program
if (cmdLoc == offset - wbl) {
cmdLoc = offset - (wbl - wbo);
}
// Colorize Environment Variable
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER);
// Reset Offset to re-process remainder of word
offset -= (wbl - wbo);
}
// Check for Operator
} else if (IsBOperator(wordBuffer[0])) {
// Colorize Default Text
styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT);
// Check for Comparison Operator
if ((wordBuffer[0] == '=') && (wordBuffer[1] == '=')) {
// Identify External Command / Program Location for IF
cmdLoc = offset;
// Skip next spaces
while ((cmdLoc < lengthLine) &&
(isspacechar(lineBuffer[cmdLoc]))) {
cmdLoc++;
}
// Colorize Comparison Operator
if (continueProcessing)
styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_OPERATOR);
else
styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_DEFAULT);
// Reset Offset to re-process remainder of word
offset -= (wbl - 2);
// Check for Pipe Operator
} else if ((wordBuffer[0] == '|') &&
!(IsEscaped(lineBuffer,offset - wbl + wbo) || textQuoted(lineBuffer, offset - wbl) )) {
// Reset External Command / Program Location
cmdLoc = offset - wbl + 1;
// Skip next spaces
while ((cmdLoc < lengthLine) &&
(isspacechar(lineBuffer[cmdLoc]))) {
cmdLoc++;
}
// Colorize Pipe Operator
styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR);
// Reset Offset to re-process remainder of word
offset -= (wbl - 1);
continueProcessing = true;
// Check for Other Operator
} else {
// Check for Operators: >, |, &
if (((wordBuffer[0] == '>')||
(wordBuffer[0] == ')')||
(wordBuffer[0] == '(')||
(wordBuffer[0] == '&' )) &&
!(!continueProcessing && (IsEscaped(lineBuffer,offset - wbl + wbo)
|| textQuoted(lineBuffer, offset - wbl) ))){
// Turn Keyword and External Command / Program checking back on
continueProcessing = true;
isNotAssigned=false;
}
// Colorize Other Operators
// Do not Colorize Paranthesis, quoted text and escaped operators
if (((wordBuffer[0] != ')') && (wordBuffer[0] != '(')
&& !textQuoted(lineBuffer, offset - wbl) && !IsEscaped(lineBuffer,offset - wbl + wbo))
&& !((wordBuffer[0] == '=') && !isNotAssigned ))
styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR);
else
styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_DEFAULT);
// Reset Offset to re-process remainder of word
offset -= (wbl - 1);
if ((wordBuffer[0] == '=') && isNotAssigned ){
isNotAssigned=false;
}
}
// Check for Default Text
} else {
// Read up to %, Operator or Separator
while ((wbo < wbl) &&
((wordBuffer[wbo] != '%') &&
(wordBuffer[wbo] != '!') &&
(!IsBOperator(wordBuffer[wbo])) &&
(!IsBSeparator(wordBuffer[wbo])))) {
wbo++;
}
// Colorize Default Text
styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT);
// Reset Offset to re-process remainder of word
offset -= (wbl - wbo);
}
// Skip next spaces - nothing happens if Offset was Reset
while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
offset++;
}
}
// Colorize Default Text for remainder of line - currently not lexed
styler.ColourTo(endPos, SCE_BAT_DEFAULT);
// handle line continuation for SET and ECHO commands except the last line
if (!continueProcessing && (i<startPos + length-1)) {
if (linePos==1 || (linePos==2 && lineBuffer[1]=='\r')) // empty line on Unix and Mac or on Windows
continueProcessing=true;
else {
Sci_PositionU lineContinuationPos;
if ((linePos>2) && lineBuffer[linePos-2]=='\r') // Windows EOL
lineContinuationPos=linePos-3;
else
lineContinuationPos=linePos-2; // Unix or Mac EOL
// Reset continueProcessing if line continuation was not found
if ((lineBuffer[lineContinuationPos]!='^')
|| IsEscaped(lineBuffer, lineContinuationPos)
|| textQuoted(lineBuffer, lineContinuationPos))
continueProcessing=true;
}
}
linePos = 0;
startLine = i + 1;
}
}
if (linePos > 0) { // Last line does not have ending characters
lineBuffer[linePos] = '\0';
ColouriseBatchLine(lineBuffer, linePos, startLine, startPos + length - 1,
keywordlists, styler);
}
}
static const char *const batchWordListDesc[] = {

View file

@ -30,9 +30,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
namespace {
bool IsAlphabetic(unsigned int ch)

View file

@ -19,9 +19,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static int classifyWordBullant(Sci_PositionU start, Sci_PositionU end, WordList &keywords, Accessor &styler) {
char s[100];

View file

@ -0,0 +1,407 @@
// Scintilla source code edit control
/** @file LexCIL.cxx
** Lexer for Common Intermediate Language
** Written by Jad Altahan (github.com/xv)
** CIL manual: https://www.ecma-international.org/publications/standards/Ecma-335.htm
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
#include <string>
#include <map>
#include <algorithm>
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
#include "StringCopy.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;
namespace {
// Use an unnamed namespace to protect the functions and classes from name conflicts
bool IsAWordChar(const int ch) {
return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.');
}
bool IsOperator(const int ch) {
if ((ch < 0x80) && (isalnum(ch)))
return false;
if (strchr("!%&*+-/<=>@^|~()[]{}", ch)) {
return true;
}
return false;
}
constexpr bool IsStreamCommentStyle(const int style) noexcept {
return style == SCE_CIL_COMMENT;
}
struct OptionsCIL {
bool fold;
bool foldComment;
bool foldCommentMultiline;
bool foldCompact;
OptionsCIL() {
fold = true;
foldComment = false;
foldCommentMultiline = true;
foldCompact = true;
}
};
static const char *const cilWordListDesc[] = {
"Primary CIL keywords",
"Metadata",
"Opcode instructions",
0
};
struct OptionSetCIL : public OptionSet<OptionsCIL> {
OptionSetCIL() {
DefineProperty("fold", &OptionsCIL::fold);
DefineProperty("fold.comment", &OptionsCIL::foldComment);
DefineProperty("fold.cil.comment.multiline", &OptionsCIL::foldCommentMultiline,
"Set this property to 0 to disable folding multi-line comments when fold.comment=1.");
DefineProperty("fold.compact", &OptionsCIL::foldCompact);
DefineWordListSets(cilWordListDesc);
}
};
LexicalClass lexicalClasses[] = {
// Lexer CIL SCLEX_CIL SCE_CIL_:
0, "SCE_CIL_DEFAULT", "default", "White space",
1, "SCE_CIL_COMMENT", "comment", "Multi-line comment",
2, "SCE_CIL_COMMENTLINE", "comment line", "Line comment",
3, "SCE_CIL_WORD", "keyword", "Keyword 1",
4, "SCE_CIL_WORD2", "keyword", "Keyword 2",
5, "SCE_CIL_WORD3", "keyword", "Keyword 3",
6, "SCE_CIL_STRING", "literal string", "Double quoted string",
7, "SCE_CIL_LABEL", "label", "Code label",
8, "SCE_CIL_OPERATOR", "operator", "Operators",
9, "SCE_CIL_STRINGEOL", "error literal string", "String is not closed",
10, "SCE_CIL_IDENTIFIER", "identifier", "Identifiers",
};
}
class LexerCIL : public DefaultLexer {
WordList keywords, keywords2, keywords3;
OptionsCIL options;
OptionSetCIL osCIL;
public:
LexerCIL() : DefaultLexer("cil", SCLEX_CIL, lexicalClasses, ELEMENTS(lexicalClasses)) { }
virtual ~LexerCIL() { }
void SCI_METHOD Release() override {
delete this;
}
int SCI_METHOD Version() const override {
return lvIdentity;
}
const char * SCI_METHOD PropertyNames() override {
return osCIL.PropertyNames();
}
int SCI_METHOD PropertyType(const char *name) override {
return osCIL.PropertyType(name);
}
const char * SCI_METHOD DescribeProperty(const char *name) override {
return osCIL.DescribeProperty(name);
}
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
const char * SCI_METHOD PropertyGet(const char* key) override {
return osCIL.PropertyGet(key);
}
const char * SCI_METHOD DescribeWordListSets() override {
return osCIL.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 0;
}
int SCI_METHOD LineEndTypesSupported() override {
return SC_LINE_END_TYPE_UNICODE;
}
int SCI_METHOD PrimaryStyleFromStyle(int style) override {
return style;
}
static ILexer *LexerFactoryCIL() {
return new LexerCIL();
}
};
Sci_Position SCI_METHOD LexerCIL::PropertySet(const char *key, const char *val) {
if (osCIL.PropertySet(&options, key, val)) {
return 0;
}
return -1;
}
Sci_Position SCI_METHOD LexerCIL::WordListSet(int n, const char *wl) {
WordList *wordListN = 0;
switch (n) {
case 0:
wordListN = &keywords;
break;
case 1:
wordListN = &keywords2;
break;
case 2:
wordListN = &keywords3;
break;
}
Sci_Position firstModification = -1;
if (wordListN) {
WordList wlNew;
wlNew.Set(wl);
if (*wordListN != wlNew) {
wordListN->Set(wl);
firstModification = 0;
}
}
return firstModification;
}
void SCI_METHOD LexerCIL::Lex(Sci_PositionU startPos, Sci_Position length,
int initStyle, IDocument *pAccess) {
if (initStyle == SCE_CIL_STRINGEOL) {
initStyle = SCE_CIL_DEFAULT;
}
Accessor styler(pAccess, NULL);
StyleContext sc(startPos, length, initStyle, styler);
bool identAtLineStart = false, // Checks if an identifier is at line start (ignoring spaces)
canStyleLabels = false; // Checks if conditions are met to style SCE_CIL_LABEL
for (; sc.More(); sc.Forward()) {
if (sc.atLineStart) {
if (sc.state == SCE_CIL_STRING) {
sc.SetState(SCE_CIL_STRING);
}
identAtLineStart = true;
}
// Handle string line continuation
if (sc.ch == '\\' && (sc.chNext == '\n' || sc.chNext == '\r') &&
(sc.state == SCE_CIL_STRING)) {
sc.Forward();
if (sc.ch == '\r' && sc.chNext == '\n') {
sc.Forward();
}
continue;
}
switch (sc.state) {
case SCE_CIL_OPERATOR:
sc.SetState(SCE_CIL_DEFAULT);
break;
case SCE_CIL_IDENTIFIER:
if (!IsAWordChar(sc.ch)) {
if (canStyleLabels && (sc.ch == ':' && sc.chNext != ':')) {
sc.ChangeState(SCE_CIL_LABEL);
sc.ForwardSetState(SCE_CIL_DEFAULT);
} else {
char kwSize[100];
sc.GetCurrent(kwSize, sizeof(kwSize));
int style = SCE_CIL_IDENTIFIER;
if (keywords.InList(kwSize)) {
style = SCE_CIL_WORD;
} else if (keywords2.InList(kwSize)) {
style = SCE_CIL_WORD2;
} else if (keywords3.InList(kwSize)) {
style = SCE_CIL_WORD3;
}
sc.ChangeState(style);
sc.SetState(SCE_CIL_DEFAULT);
}
}
break;
case SCE_CIL_COMMENT:
if (sc.Match('*', '/')) {
sc.Forward();
sc.ForwardSetState(SCE_CIL_DEFAULT);
}
break;
case SCE_CIL_COMMENTLINE:
if (sc.atLineStart) {
sc.SetState(SCE_CIL_DEFAULT);
}
break;
case SCE_CIL_STRING:
if (sc.ch == '\\') {
if (sc.chNext == '"' || sc.chNext == '\\') {
sc.Forward();
}
} else if (sc.ch == '"') {
sc.ForwardSetState(SCE_CIL_DEFAULT);
} else if (sc.atLineEnd) {
sc.ChangeState(SCE_CIL_STRINGEOL);
sc.ForwardSetState(SCE_CIL_DEFAULT);
}
break;
}
if (sc.state == SCE_CIL_DEFAULT) {
// String
if (sc.ch == '"') {
sc.SetState(SCE_CIL_STRING);
}
// Keyword
else if (IsAWordChar(sc.ch)) {
// Allow setting SCE_CIL_LABEL style only if the label is the
// first token in the line and does not start with a dot or a digit
canStyleLabels = identAtLineStart && !(sc.ch == '.' || IsADigit(sc.ch));
sc.SetState(SCE_CIL_IDENTIFIER);
}
// Multi-line comment
else if (sc.Match('/', '*')) {
sc.SetState(SCE_CIL_COMMENT);
sc.Forward();
}
// Line comment
else if (sc.Match('/', '/')) {
sc.SetState(SCE_CIL_COMMENTLINE);
}
// Operators
else if (IsOperator(sc.ch)) {
sc.SetState(SCE_CIL_OPERATOR);
}
}
if (!IsASpace(sc.ch)) {
identAtLineStart = false;
}
}
sc.Complete();
}
void SCI_METHOD LexerCIL::Fold(Sci_PositionU startPos, Sci_Position length,
int initStyle, IDocument *pAccess) {
if (!options.fold) {
return;
}
LexAccessor styler(pAccess);
const Sci_PositionU endPos = startPos + length;
Sci_Position lineCurrent = styler.GetLine(startPos);
int levelCurrent = SC_FOLDLEVELBASE;
if (lineCurrent > 0)
levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16;
int style = initStyle;
int styleNext = styler.StyleAt(startPos);
int levelNext = levelCurrent;
int visibleChars = 0;
char chNext = styler[startPos];
for (Sci_PositionU i = startPos; i < endPos; i++) {
const char ch = chNext;
int stylePrev = style;
chNext = styler.SafeGetCharAt(i + 1);
style = styleNext;
styleNext = styler.StyleAt(i + 1);
const bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
if (options.foldComment &&
options.foldCommentMultiline && IsStreamCommentStyle(style)) {
if (!IsStreamCommentStyle(stylePrev)) {
levelNext++;
} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
levelNext--;
}
}
if (style == SCE_CIL_OPERATOR) {
if (ch == '{') {
levelNext++;
} else if (ch == '}') {
levelNext--;
}
}
if (!IsASpace(ch)) {
visibleChars++;
}
if (atEOL || (i == endPos - 1)) {
int lev = levelCurrent | levelNext << 16;
if (visibleChars == 0 && options.foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG;
if (levelCurrent < levelNext)
lev |= SC_FOLDLEVELHEADERFLAG;
if (lev != styler.LevelAt(lineCurrent)) {
styler.SetLevel(lineCurrent, lev);
}
lineCurrent++;
levelCurrent = levelNext;
if (options.foldCompact &&
i == static_cast<Sci_PositionU>(styler.Length() - 1)) {
styler.SetLevel(lineCurrent, lev | SC_FOLDLEVELWHITEFLAG);
}
visibleChars = 0;
}
}
}
LexerModule lmCIL(SCLEX_CIL, LexerCIL::LexerFactoryCIL, "cil", cilWordListDesc);

View file

@ -1,5 +1,5 @@
// Scintilla source code edit control
/** @file LexClw.cxx
/** @file LexCLW.cxx
** Lexer for Clarion.
** 2004/12/17 Updated Lexer
**/
@ -24,9 +24,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
// Is an end of line character
inline bool IsEOL(const int ch) {

View file

@ -26,9 +26,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
#define IN_DIVISION 0x01
#define IN_DECLARATIVES 0x02

View file

@ -6,22 +6,22 @@
// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <utility>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include <iterator>
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
#include "StringCopy.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
@ -32,14 +32,12 @@
#include "SparseState.h"
#include "SubStyles.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
namespace {
// Use an unnamed namespace to protect the functions and classes from name conflicts
bool IsSpaceEquiv(int state) {
constexpr bool IsSpaceEquiv(int state) noexcept {
return (state <= SCE_C_COMMENTDOC) ||
// including SCE_C_DEFAULT, SCE_C_COMMENT, SCE_C_COMMENTLINE
(state == SCE_C_COMMENTLINEDOC) || (state == SCE_C_COMMENTDOCKEYWORD) ||
@ -53,10 +51,10 @@ bool IsSpaceEquiv(int state) {
// a = b+++/ptn/...
// Putting a space between the '++' post-inc operator and the '+' binary op
// fixes this, and is highly recommended for readability anyway.
bool FollowsPostfixOperator(StyleContext &sc, LexAccessor &styler) {
Sci_Position pos = (Sci_Position) sc.currentPos;
bool FollowsPostfixOperator(const StyleContext &sc, LexAccessor &styler) {
Sci_Position pos = sc.currentPos;
while (--pos > 0) {
char ch = styler[pos];
const char ch = styler[pos];
if (ch == '+' || ch == '-') {
return styler[pos - 1] == ch;
}
@ -64,13 +62,13 @@ bool FollowsPostfixOperator(StyleContext &sc, LexAccessor &styler) {
return false;
}
bool followsReturnKeyword(StyleContext &sc, LexAccessor &styler) {
bool followsReturnKeyword(const StyleContext &sc, LexAccessor &styler) {
// Don't look at styles, so no need to flush.
Sci_Position pos = (Sci_Position) sc.currentPos;
Sci_Position currentLine = styler.GetLine(pos);
Sci_Position lineStartPos = styler.LineStart(currentLine);
Sci_Position pos = sc.currentPos;
const Sci_Position currentLine = styler.GetLine(pos);
const Sci_Position lineStartPos = styler.LineStart(currentLine);
while (--pos > lineStartPos) {
char ch = styler.SafeGetCharAt(pos);
const char ch = styler.SafeGetCharAt(pos);
if (ch != ' ' && ch != '\t') {
break;
}
@ -86,13 +84,13 @@ bool followsReturnKeyword(StyleContext &sc, LexAccessor &styler) {
return !*s;
}
bool IsSpaceOrTab(int ch) {
constexpr bool IsSpaceOrTab(int ch) noexcept {
return ch == ' ' || ch == '\t';
}
bool OnlySpaceOrTab(const std::string &s) {
for (std::string::const_iterator it = s.begin(); it != s.end(); ++it) {
if (!IsSpaceOrTab(*it))
bool OnlySpaceOrTab(const std::string &s) noexcept {
for (const char ch : s) {
if (!IsSpaceOrTab(ch))
return false;
}
return true;
@ -100,11 +98,11 @@ bool OnlySpaceOrTab(const std::string &s) {
std::vector<std::string> StringSplit(const std::string &text, int separator) {
std::vector<std::string> vs(text.empty() ? 0 : 1);
for (std::string::const_iterator it = text.begin(); it != text.end(); ++it) {
if (*it == separator) {
vs.push_back(std::string());
for (const char ch : text) {
if (ch == separator) {
vs.emplace_back();
} else {
vs.back() += *it;
vs.back() += ch;
}
}
return vs;
@ -141,21 +139,21 @@ BracketPair FindBracketPair(std::vector<std::string> &tokens) {
}
void highlightTaskMarker(StyleContext &sc, LexAccessor &styler,
int activity, WordList &markerList, bool caseSensitive){
int activity, const WordList &markerList, bool caseSensitive){
if ((isoperator(sc.chPrev) || IsASpace(sc.chPrev)) && markerList.Length()) {
const int lengthMarker = 50;
char marker[lengthMarker+1];
Sci_Position currPos = (Sci_Position) sc.currentPos;
int i = 0;
constexpr Sci_PositionU lengthMarker = 50;
char marker[lengthMarker+1] = "";
const Sci_PositionU currPos = sc.currentPos;
Sci_PositionU i = 0;
while (i < lengthMarker) {
char ch = styler.SafeGetCharAt(currPos + i);
const char ch = styler.SafeGetCharAt(currPos + i);
if (IsASpace(ch) || isoperator(ch)) {
break;
}
if (caseSensitive)
marker[i] = ch;
else
marker[i] = static_cast<char>(tolower(ch));
marker[i] = MakeLowerCase(ch);
i++;
}
marker[i] = '\0';
@ -165,18 +163,14 @@ void highlightTaskMarker(StyleContext &sc, LexAccessor &styler,
}
}
struct EscapeSequence {
int digitsLeft;
CharacterSet setHexDigits;
CharacterSet setOctDigits;
CharacterSet setNoneNumeric;
CharacterSet *escapeSetValid;
EscapeSequence() {
digitsLeft = 0;
escapeSetValid = 0;
setHexDigits = CharacterSet(CharacterSet::setDigits, "ABCDEFabcdef");
setOctDigits = CharacterSet(CharacterSet::setNone, "01234567");
}
class EscapeSequence {
const CharacterSet setHexDigits = CharacterSet(CharacterSet::setDigits, "ABCDEFabcdef");
const CharacterSet setOctDigits = CharacterSet(CharacterSet::setNone, "01234567");
const CharacterSet setNoneNumeric;
const CharacterSet *escapeSetValid = nullptr;
int digitsLeft = 0;
public:
EscapeSequence() = default;
void resetEscapeState(int nextChar) {
digitsLeft = 0;
escapeSetValid = &setNoneNumeric;
@ -197,26 +191,39 @@ struct EscapeSequence {
bool atEscapeEnd(int currChar) const {
return (digitsLeft <= 0) || !escapeSetValid->Contains(currChar);
}
void consumeDigit() noexcept {
digitsLeft--;
}
};
std::string GetRestOfLine(LexAccessor &styler, Sci_Position start, bool allowSpace) {
std::string restOfLine;
Sci_Position i =0;
Sci_Position line = styler.GetLine(start);
Sci_Position pos = start;
Sci_Position endLine = styler.LineEnd(line);
char ch = styler.SafeGetCharAt(start, '\n');
Sci_Position endLine = styler.LineEnd(styler.GetLine(start));
while (((start+i) < endLine) && (ch != '\r')) {
char chNext = styler.SafeGetCharAt(start + i + 1, '\n');
if (ch == '/' && (chNext == '/' || chNext == '*'))
break;
if (allowSpace || (ch != ' '))
restOfLine += ch;
i++;
ch = chNext;
while (pos < endLine) {
if (ch == '\\' && ((pos + 1) == endLine)) {
// Continuation line
line++;
pos = styler.LineStart(line);
endLine = styler.LineEnd(line);
ch = styler.SafeGetCharAt(pos, '\n');
} else {
const char chNext = styler.SafeGetCharAt(pos + 1, '\n');
if (ch == '/' && (chNext == '/' || chNext == '*'))
break;
if (allowSpace || (ch != ' ')) {
restOfLine += ch;
}
pos++;
ch = chNext;
}
}
return restOfLine;
}
bool IsStreamCommentStyle(int style) {
constexpr bool IsStreamCommentStyle(int style) noexcept {
return style == SCE_C_COMMENT ||
style == SCE_C_COMMENTDOC ||
style == SCE_C_COMMENTDOCKEYWORD ||
@ -234,26 +241,48 @@ struct PPDefinition {
}
};
constexpr int inactiveFlag = 0x40;
class LinePPState {
int state;
int ifTaken;
int level;
bool ValidLevel() const {
return level >= 0 && level < 32;
// Track the state of preprocessor conditionals to allow showing active and inactive
// code in different styles.
// Only works up to 31 levels of conditional nesting.
// state is a bit mask with 1 bit per level
// bit is 1 for level if section inactive, so any bits set = inactive style
int state = 0;
// ifTaken is a bit mask with 1 bit per level
// bit is 1 for level if some branch at this level has been taken
int ifTaken = 0;
// level is the nesting level of #if constructs
int level = -1;
static const int maximumNestingLevel = 31;
bool ValidLevel() const noexcept {
return level >= 0 && level < maximumNestingLevel;
}
int maskLevel() const {
return 1 << level;
int maskLevel() const noexcept {
if (level >= 0) {
return 1 << level;
} else {
return 1;
}
}
public:
LinePPState() : state(0), ifTaken(0), level(-1) {
LinePPState() noexcept {
}
bool IsInactive() const {
bool IsActive() const noexcept {
return state == 0;
}
bool IsInactive() const noexcept {
return state != 0;
}
bool CurrentIfTaken() const {
int ActiveState() const noexcept {
return state ? inactiveFlag : 0;
}
bool CurrentIfTaken() const noexcept {
return (ifTaken & maskLevel()) != 0;
}
void StartSection(bool on) {
void StartSection(bool on) noexcept {
level++;
if (ValidLevel()) {
if (on) {
@ -265,14 +294,14 @@ public:
}
}
}
void EndSection() {
void EndSection() noexcept {
if (ValidLevel()) {
state &= ~maskLevel();
ifTaken &= ~maskLevel();
}
level--;
}
void InvertCurrentLevel() {
void InvertCurrentLevel() noexcept {
if (ValidLevel()) {
state ^= maskLevel();
ifTaken |= maskLevel();
@ -285,7 +314,7 @@ public:
class PPStates {
std::vector<LinePPState> vlls;
public:
LinePPState ForLine(Sci_Position line) const {
LinePPState ForLine(Sci_Position line) const noexcept {
if ((line > 0) && (vlls.size() > static_cast<size_t>(line))) {
return vlls[line];
} else {
@ -355,7 +384,7 @@ const char *const cppWordLists[] = {
"Global classes and typedefs",
"Preprocessor definitions",
"Task marker and error marker keywords",
0,
nullptr,
};
struct OptionSetCPP : public OptionSet<OptionsCPP> {
@ -432,13 +461,48 @@ struct OptionSetCPP : public OptionSet<OptionsCPP> {
const char styleSubable[] = {SCE_C_IDENTIFIER, SCE_C_COMMENTDOCKEYWORD, 0};
LexicalClass lexicalClasses[] = {
// Lexer Cpp SCLEX_CPP SCE_C_:
0, "SCE_C_DEFAULT", "default", "White space",
1, "SCE_C_COMMENT", "comment", "Comment: /* */.",
2, "SCE_C_COMMENTLINE", "comment line", "Line Comment: //.",
3, "SCE_C_COMMENTDOC", "comment documentation", "Doc comment: block comments beginning with /** or /*!",
4, "SCE_C_NUMBER", "literal numeric", "Number",
5, "SCE_C_WORD", "keyword", "Keyword",
6, "SCE_C_STRING", "literal string", "Double quoted string",
7, "SCE_C_CHARACTER", "literal string character", "Single quoted string",
8, "SCE_C_UUID", "literal uuid", "UUIDs (only in IDL)",
9, "SCE_C_PREPROCESSOR", "preprocessor", "Preprocessor",
10, "SCE_C_OPERATOR", "operator", "Operators",
11, "SCE_C_IDENTIFIER", "identifier", "Identifiers",
12, "SCE_C_STRINGEOL", "error literal string", "End of line where string is not closed",
13, "SCE_C_VERBATIM", "literal string multiline raw", "Verbatim strings for C#",
14, "SCE_C_REGEX", "literal regex", "Regular expressions for JavaScript",
15, "SCE_C_COMMENTLINEDOC", "comment documentation line", "Doc Comment Line: line comments beginning with /// or //!.",
16, "SCE_C_WORD2", "identifier", "Keywords2",
17, "SCE_C_COMMENTDOCKEYWORD", "comment documentation keyword", "Comment keyword",
18, "SCE_C_COMMENTDOCKEYWORDERROR", "error comment documentation keyword", "Comment keyword error",
19, "SCE_C_GLOBALCLASS", "identifier", "Global class",
20, "SCE_C_STRINGRAW", "literal string multiline raw", "Raw strings for C++0x",
21, "SCE_C_TRIPLEVERBATIM", "literal string multiline raw", "Triple-quoted strings for Vala",
22, "SCE_C_HASHQUOTEDSTRING", "literal string", "Hash-quoted strings for Pike",
23, "SCE_C_PREPROCESSORCOMMENT", "comment preprocessor", "Preprocessor stream comment",
24, "SCE_C_PREPROCESSORCOMMENTDOC", "comment preprocessor documentation", "Preprocessor stream doc comment",
25, "SCE_C_USERLITERAL", "literal", "User defined literals",
26, "SCE_C_TASKMARKER", "comment taskmarker", "Task Marker",
27, "SCE_C_ESCAPESEQUENCE", "literal string escapesequence", "Escape sequence",
};
const int sizeLexicalClasses = static_cast<int>(Sci::size(lexicalClasses));
}
class LexerCPP : public ILexerWithSubStyles {
class LexerCPP : public ILexerWithIdentity {
bool caseSensitive;
CharacterSet setWord;
CharacterSet setNegationOp;
CharacterSet setArithmethicOp;
CharacterSet setAddOp;
CharacterSet setMultOp;
CharacterSet setRelOp;
CharacterSet setLogicalOp;
CharacterSet setWordStart;
@ -453,14 +517,15 @@ class LexerCPP : public ILexerWithSubStyles {
struct SymbolValue {
std::string value;
std::string arguments;
SymbolValue(const std::string &value_="", const std::string &arguments_="") : value(value_), arguments(arguments_) {
SymbolValue() = default;
SymbolValue(const std::string &value_, const std::string &arguments_) : value(value_), arguments(arguments_) {
}
SymbolValue &operator = (const std::string &value_) {
value = value_;
arguments.clear();
return *this;
}
bool IsMacro() const {
bool IsMacro() const noexcept {
return !arguments.empty();
}
};
@ -470,81 +535,149 @@ class LexerCPP : public ILexerWithSubStyles {
OptionSetCPP osCPP;
EscapeSequence escapeSeq;
SparseState<std::string> rawStringTerminators;
enum { activeFlag = 0x40 };
enum { ssIdentifier, ssDocKeyword };
SubStyles subStyles;
std::string returnBuffer;
public:
explicit LexerCPP(bool caseSensitive_) :
caseSensitive(caseSensitive_),
setWord(CharacterSet::setAlphaNum, "._", 0x80, true),
setNegationOp(CharacterSet::setNone, "!"),
setArithmethicOp(CharacterSet::setNone, "+-/*%"),
setAddOp(CharacterSet::setNone, "+-"),
setMultOp(CharacterSet::setNone, "*/%"),
setRelOp(CharacterSet::setNone, "=!<>"),
setLogicalOp(CharacterSet::setNone, "|&"),
subStyles(styleSubable, 0x80, 0x40, activeFlag) {
subStyles(styleSubable, 0x80, 0x40, inactiveFlag) {
}
// Deleted so LexerCPP objects can not be copied.
LexerCPP(const LexerCPP &) = delete;
LexerCPP(LexerCPP &&) = delete;
void operator=(const LexerCPP &) = delete;
void operator=(LexerCPP &&) = delete;
virtual ~LexerCPP() {
}
void SCI_METHOD Release() {
void SCI_METHOD Release() noexcept override {
delete this;
}
int SCI_METHOD Version() const {
return lvSubStyles;
int SCI_METHOD Version() const noexcept override {
return lvIdentity;
}
const char * SCI_METHOD PropertyNames() {
const char * SCI_METHOD PropertyNames() override {
return osCPP.PropertyNames();
}
int SCI_METHOD PropertyType(const char *name) {
int SCI_METHOD PropertyType(const char *name) override {
return osCPP.PropertyType(name);
}
const char * SCI_METHOD DescribeProperty(const char *name) {
const char * SCI_METHOD DescribeProperty(const char *name) override {
return osCPP.DescribeProperty(name);
}
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val);
const char * SCI_METHOD DescribeWordListSets() {
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
const char * SCI_METHOD DescribeWordListSets() override {
return osCPP.DescribeWordListSets();
}
Sci_Position SCI_METHOD WordListSet(int n, const char *wl);
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess);
void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess);
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 *) {
return 0;
void * SCI_METHOD PrivateCall(int, void *) noexcept override {
return nullptr;
}
int SCI_METHOD LineEndTypesSupported() {
int SCI_METHOD LineEndTypesSupported() noexcept override {
return SC_LINE_END_TYPE_UNICODE;
}
int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) {
int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) override {
return subStyles.Allocate(styleBase, numberStyles);
}
int SCI_METHOD SubStylesStart(int styleBase) {
int SCI_METHOD SubStylesStart(int styleBase) override {
return subStyles.Start(styleBase);
}
int SCI_METHOD SubStylesLength(int styleBase) {
int SCI_METHOD SubStylesLength(int styleBase) override {
return subStyles.Length(styleBase);
}
int SCI_METHOD StyleFromSubStyle(int subStyle) {
int styleBase = subStyles.BaseStyle(MaskActive(subStyle));
int active = subStyle & activeFlag;
return styleBase | active;
int SCI_METHOD StyleFromSubStyle(int subStyle) override {
const int styleBase = subStyles.BaseStyle(MaskActive(subStyle));
const int inactive = subStyle & inactiveFlag;
return styleBase | inactive;
}
int SCI_METHOD PrimaryStyleFromStyle(int style) {
int SCI_METHOD PrimaryStyleFromStyle(int style) noexcept override {
return MaskActive(style);
}
void SCI_METHOD FreeSubStyles() {
}
void SCI_METHOD FreeSubStyles() override {
subStyles.Free();
}
void SCI_METHOD SetIdentifiers(int style, const char *identifiers) {
void SCI_METHOD SetIdentifiers(int style, const char *identifiers) override {
subStyles.SetIdentifiers(style, identifiers);
}
int SCI_METHOD DistanceToSecondaryStyles() {
return activeFlag;
int SCI_METHOD DistanceToSecondaryStyles() noexcept override {
return inactiveFlag;
}
const char * SCI_METHOD GetSubStyleBases() {
const char * SCI_METHOD GetSubStyleBases() noexcept override {
return styleSubable;
}
int SCI_METHOD NamedStyles() override {
return std::max(subStyles.LastAllocated() + 1,
sizeLexicalClasses) +
inactiveFlag;
}
const char * SCI_METHOD NameOfStyle(int style) override {
if (style >= NamedStyles())
return "";
if (style < sizeLexicalClasses)
return lexicalClasses[style].name;
// TODO: inactive and substyles
return "";
}
const char * SCI_METHOD TagsOfStyle(int style) override {
if (style >= NamedStyles())
return "Excess";
returnBuffer.clear();
const int firstSubStyle = subStyles.FirstAllocated();
if (firstSubStyle >= 0) {
const int lastSubStyle = subStyles.LastAllocated();
if (((style >= firstSubStyle) && (style <= (lastSubStyle))) ||
((style >= firstSubStyle + inactiveFlag) && (style <= (lastSubStyle + inactiveFlag)))) {
int styleActive = style;
if (style > lastSubStyle) {
returnBuffer = "inactive ";
styleActive -= inactiveFlag;
}
const int styleMain = StyleFromSubStyle(styleActive);
returnBuffer += lexicalClasses[styleMain].tags;
return returnBuffer.c_str();
}
}
if (style < sizeLexicalClasses)
return lexicalClasses[style].tags;
if (style >= inactiveFlag) {
returnBuffer = "inactive ";
const int styleActive = style - inactiveFlag;
if (styleActive < sizeLexicalClasses)
returnBuffer += lexicalClasses[styleActive].tags;
else
returnBuffer = "";
return returnBuffer.c_str();
}
return "";
}
const char * SCI_METHOD DescriptionOfStyle(int style) override {
if (style >= NamedStyles())
return "";
if (style < sizeLexicalClasses)
return lexicalClasses[style].description;
// TODO: inactive and substyles
return "";
}
// ILexerWithIdentity methods
const char * SCI_METHOD GetName() override {
return caseSensitive ? "cpp" : "cppnocase";
}
int SCI_METHOD GetIdentifier() override {
return caseSensitive ? SCLEX_CPP : SCLEX_CPPNOCASE;
}
const char * SCI_METHOD PropertyGet(const char *key) override;
static ILexer *LexerFactoryCPP() {
return new LexerCPP(true);
@ -552,8 +685,8 @@ public:
static ILexer *LexerFactoryCPPInsensitive() {
return new LexerCPP(false);
}
static int MaskActive(int style) {
return style & ~activeFlag;
constexpr static int MaskActive(int style) noexcept {
return style & ~inactiveFlag;
}
void EvaluateTokens(std::vector<std::string> &tokens, const SymbolTable &preprocessorDefinitions);
std::vector<std::string> Tokenize(const std::string &expr) const;
@ -573,8 +706,12 @@ Sci_Position SCI_METHOD LexerCPP::PropertySet(const char *key, const char *val)
return -1;
}
const char * SCI_METHOD LexerCPP::PropertyGet(const char *key) {
return osCPP.PropertyGet(key);
}
Sci_Position SCI_METHOD LexerCPP::WordListSet(int n, const char *wl) {
WordList *wordListN = 0;
WordList *wordListN = nullptr;
switch (n) {
case 0:
wordListN = &keywords;
@ -611,8 +748,8 @@ Sci_Position SCI_METHOD LexerCPP::WordListSet(int n, const char *wl) {
if (cpEquals) {
std::string name(cpDefinition, cpEquals - cpDefinition);
std::string val(cpEquals+1);
size_t bracket = name.find('(');
size_t bracketEnd = name.find(')');
const size_t bracket = name.find('(');
const size_t bracketEnd = name.find(')');
if ((bracket != std::string::npos) && (bracketEnd != std::string::npos)) {
// Macro
std::string args = name.substr(bracket + 1, bracketEnd - bracket - 1);
@ -633,15 +770,6 @@ Sci_Position SCI_METHOD LexerCPP::WordListSet(int n, const char *wl) {
return firstModification;
}
// Functor used to truncate history
struct After {
Sci_Position line;
explicit After(Sci_Position line_) : line(line_) {}
bool operator()(PPDefinition &p) const {
return p.line > line;
}
};
void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) {
LexAccessor styler(pAccess);
@ -675,7 +803,7 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
(MaskActive(initStyle) == SCE_C_COMMENTLINEDOC)) {
// Set continuationLine if last character of previous line is '\'
if (lineCurrent > 0) {
Sci_Position endLinePrevious = styler.LineEnd(lineCurrent - 1);
const Sci_Position endLinePrevious = styler.LineEnd(lineCurrent - 1);
if (endLinePrevious > 0) {
continuationLine = styler.SafeGetCharAt(endLinePrevious-1) == '\\';
}
@ -702,29 +830,30 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
if (!options.updatePreprocessor)
ppDefineHistory.clear();
std::vector<PPDefinition>::iterator itInvalid = std::find_if(ppDefineHistory.begin(), ppDefineHistory.end(), After(lineCurrent-1));
std::vector<PPDefinition>::iterator itInvalid = std::find_if(ppDefineHistory.begin(), ppDefineHistory.end(),
[lineCurrent](const PPDefinition &p) noexcept { return p.line >= lineCurrent; });
if (itInvalid != ppDefineHistory.end()) {
ppDefineHistory.erase(itInvalid, ppDefineHistory.end());
definitionsChanged = true;
}
SymbolTable preprocessorDefinitions = preprocessorDefinitionsStart;
for (std::vector<PPDefinition>::iterator itDef = ppDefineHistory.begin(); itDef != ppDefineHistory.end(); ++itDef) {
if (itDef->isUndef)
preprocessorDefinitions.erase(itDef->key);
for (const PPDefinition &ppDef : ppDefineHistory) {
if (ppDef.isUndef)
preprocessorDefinitions.erase(ppDef.key);
else
preprocessorDefinitions[itDef->key] = SymbolValue(itDef->value, itDef->arguments);
preprocessorDefinitions[ppDef.key] = SymbolValue(ppDef.value, ppDef.arguments);
}
std::string rawStringTerminator = rawStringTerminators.ValueAt(lineCurrent-1);
SparseState<std::string> rawSTNew(lineCurrent);
int activitySet = preproc.IsInactive() ? activeFlag : 0;
int activitySet = preproc.ActiveState();
const WordClassifier &classifierIdentifiers = subStyles.Classifier(SCE_C_IDENTIFIER);
const WordClassifier &classifierDocKeyWords = subStyles.Classifier(SCE_C_COMMENTDOCKEYWORD);
Sci_Position lineEndNext = styler.LineEnd(lineCurrent);
Sci_PositionU lineEndNext = styler.LineEnd(lineCurrent);
for (; sc.More();) {
@ -746,7 +875,7 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
isIncludePreprocessor = false;
inRERange = false;
if (preproc.IsInactive()) {
activitySet = activeFlag;
activitySet = inactiveFlag;
sc.SetState(sc.state | activitySet);
}
}
@ -762,7 +891,7 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
// Handle line continuation generically.
if (sc.ch == '\\') {
if (static_cast<Sci_Position>((sc.currentPos+1)) >= lineEndNext) {
if ((sc.currentPos+1) >= lineEndNext) {
lineCurrent++;
lineEndNext = styler.LineEnd(lineCurrent);
vlls.Add(lineCurrent, preproc);
@ -829,7 +958,7 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
const bool raw = literalString && sc.chPrev == 'R' && !setInvalidRawFirst.Contains(sc.chNext);
if (raw)
s[lenS--] = '\0';
bool valid =
const bool valid =
(lenS == 0) ||
((lenS == 1) && ((s[0] == 'L') || (s[0] == 'u') || (s[0] == 'U'))) ||
((lenS == 2) && literalString && (s[0] == 'u') && (s[1] == '8'));
@ -856,7 +985,7 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
break;
case SCE_C_PREPROCESSOR:
if (options.stylingWithinPreprocessor) {
if (IsASpace(sc.ch)) {
if (IsASpace(sc.ch) || (sc.ch == '(')) {
sc.SetState(SCE_C_DEFAULT|activitySet);
}
} else if (isStringInPreprocessor && (sc.Match('>') || sc.Match('\"') || sc.atLineEnd)) {
@ -977,7 +1106,7 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
}
break;
case SCE_C_ESCAPESEQUENCE:
escapeSeq.digitsLeft--;
escapeSeq.consumeDigit();
if (!escapeSeq.atEscapeEnd(sc.ch)) {
break;
}
@ -1029,12 +1158,12 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
case SCE_C_REGEX:
if (sc.atLineStart) {
sc.SetState(SCE_C_DEFAULT|activitySet);
} else if (! inRERange && sc.ch == '/') {
} else if (!inRERange && sc.ch == '/') {
sc.Forward();
while ((sc.ch < 0x80) && islower(sc.ch))
while (IsLowerCase(sc.ch))
sc.Forward(); // gobble regex flags
sc.SetState(SCE_C_DEFAULT|activitySet);
} else if (sc.ch == '\\' && (static_cast<Sci_Position>(sc.currentPos+1) < lineEndNext)) {
} else if (sc.ch == '\\' && ((sc.currentPos+1) < lineEndNext)) {
// Gobble up the escaped character
sc.Forward();
} else if (sc.ch == '[') {
@ -1060,7 +1189,7 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
}
break;
case SCE_C_TRIPLEVERBATIM:
if (sc.Match("\"\"\"")) {
if (sc.Match(R"(""")")) {
while (sc.Match('"')) {
sc.Forward();
}
@ -1091,7 +1220,7 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
if (sc.Match('@', '\"')) {
sc.SetState(SCE_C_VERBATIM|activitySet);
sc.Forward();
} else if (options.triplequotedStrings && sc.Match("\"\"\"")) {
} else if (options.triplequotedStrings && sc.Match(R"(""")")) {
sc.SetState(SCE_C_TRIPLEVERBATIM|activitySet);
sc.Forward(2);
} else if (options.hashquotedStrings && sc.Match('#', '\"')) {
@ -1141,7 +1270,7 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
sc.SetState(SCE_C_STRINGRAW|activitySet);
rawStringTerminator = ")";
for (Sci_Position termPos = sc.currentPos + 1;; termPos++) {
char chTerminator = styler.SafeGetCharAt(termPos, '(');
const char chTerminator = styler.SafeGetCharAt(termPos, '(');
if (chTerminator == '(')
break;
rawStringTerminator += chTerminator;
@ -1171,58 +1300,71 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
isIncludePreprocessor = true;
} else {
if (options.trackPreprocessor) {
// If #if is nested too deeply (>31 levels) the active/inactive appearance
// will stop reflecting the code.
if (sc.Match("ifdef") || sc.Match("ifndef")) {
bool isIfDef = sc.Match("ifdef");
int i = isIfDef ? 5 : 6;
std::string restOfLine = GetRestOfLine(styler, sc.currentPos + i + 1, false);
const bool isIfDef = sc.Match("ifdef");
const int startRest = isIfDef ? 5 : 6;
std::string restOfLine = GetRestOfLine(styler, sc.currentPos + startRest + 1, false);
bool foundDef = preprocessorDefinitions.find(restOfLine) != preprocessorDefinitions.end();
preproc.StartSection(isIfDef == foundDef);
} else if (sc.Match("if")) {
std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 2, true);
bool ifGood = EvaluateExpression(restOfLine, preprocessorDefinitions);
const bool ifGood = EvaluateExpression(restOfLine, preprocessorDefinitions);
preproc.StartSection(ifGood);
} else if (sc.Match("else")) {
// #else is shown as active if either preceding or following section is active
// as that means that it contributed to the result.
if (!preproc.CurrentIfTaken()) {
// Inactive, may become active if parent scope active
assert(sc.state == (SCE_C_PREPROCESSOR|inactiveFlag));
preproc.InvertCurrentLevel();
activitySet = preproc.IsInactive() ? activeFlag : 0;
activitySet = preproc.ActiveState();
// If following is active then show "else" as active
if (!activitySet)
sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
} else if (!preproc.IsInactive()) {
sc.ChangeState(SCE_C_PREPROCESSOR);
} else if (preproc.IsActive()) {
// Active -> inactive
assert(sc.state == SCE_C_PREPROCESSOR);
preproc.InvertCurrentLevel();
activitySet = preproc.IsInactive() ? activeFlag : 0;
if (!activitySet)
sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
activitySet = preproc.ActiveState();
// Continue to show "else" as active as it ends active section.
}
} else if (sc.Match("elif")) {
// Ensure only one chosen out of #if .. #elif .. #elif .. #else .. #endif
// #elif is shown as active if either preceding or following section is active
// as that means that it contributed to the result.
if (!preproc.CurrentIfTaken()) {
// Inactive, if expression true then may become active if parent scope active
assert(sc.state == (SCE_C_PREPROCESSOR|inactiveFlag));
// Similar to #if
std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 2, true);
bool ifGood = EvaluateExpression(restOfLine, preprocessorDefinitions);
std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 4, true);
const bool ifGood = EvaluateExpression(restOfLine, preprocessorDefinitions);
if (ifGood) {
preproc.InvertCurrentLevel();
activitySet = preproc.IsInactive() ? activeFlag : 0;
activitySet = preproc.ActiveState();
if (!activitySet)
sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
sc.ChangeState(SCE_C_PREPROCESSOR);
}
} else if (!preproc.IsInactive()) {
} else if (preproc.IsActive()) {
// Active -> inactive
assert(sc.state == SCE_C_PREPROCESSOR);
preproc.InvertCurrentLevel();
activitySet = preproc.IsInactive() ? activeFlag : 0;
if (!activitySet)
sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
activitySet = preproc.ActiveState();
// Continue to show "elif" as active as it ends active section.
}
} else if (sc.Match("endif")) {
preproc.EndSection();
activitySet = preproc.IsInactive() ? activeFlag : 0;
activitySet = preproc.ActiveState();
sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
} else if (sc.Match("define")) {
if (options.updatePreprocessor && !preproc.IsInactive()) {
if (options.updatePreprocessor && preproc.IsActive()) {
std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true);
size_t startName = 0;
while ((startName < restOfLine.length()) && IsSpaceOrTab(restOfLine[startName]))
startName++;
size_t endName = startName;
while ((endName < restOfLine.length()) && setWord.Contains(static_cast<unsigned char>(restOfLine[endName])))
while ((endName < restOfLine.length()) && setWord.Contains(restOfLine[endName]))
endName++;
std::string key = restOfLine.substr(startName, endName-startName);
if ((endName < restOfLine.length()) && (restOfLine.at(endName) == '(')) {
@ -1246,13 +1388,15 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
while ((startValue < restOfLine.length()) && IsSpaceOrTab(restOfLine[startValue]))
startValue++;
std::string value = restOfLine.substr(startValue);
if (OnlySpaceOrTab(value))
value = "1"; // No value defaults to 1
preprocessorDefinitions[key] = value;
ppDefineHistory.push_back(PPDefinition(lineCurrent, key, value));
definitionsChanged = true;
}
}
} else if (sc.Match("undef")) {
if (options.updatePreprocessor && !preproc.IsInactive()) {
if (options.updatePreprocessor && preproc.IsActive()) {
const std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 5, false);
std::vector<std::string> tokens = Tokenize(restOfLine);
if (tokens.size() >= 1) {
@ -1294,7 +1438,7 @@ void SCI_METHOD LexerCPP::Fold(Sci_PositionU startPos, Sci_Position length, int
LexAccessor styler(pAccess);
Sci_PositionU endPos = startPos + length;
const Sci_PositionU endPos = startPos + length;
int visibleChars = 0;
bool inLineComment = false;
Sci_Position lineCurrent = styler.GetLine(startPos);
@ -1309,12 +1453,12 @@ void SCI_METHOD LexerCPP::Fold(Sci_PositionU startPos, Sci_Position length, int
int style = MaskActive(initStyle);
const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty();
for (Sci_PositionU i = startPos; i < endPos; i++) {
char ch = chNext;
const char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
int stylePrev = style;
const int stylePrev = style;
style = styleNext;
styleNext = MaskActive(styler.StyleAt(i + 1));
bool atEOL = i == (lineStartNext-1);
const bool atEOL = i == (lineStartNext-1);
if ((style == SCE_C_COMMENTLINE) || (style == SCE_C_COMMENTLINEDOC))
inLineComment = true;
if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style) && !inLineComment) {
@ -1334,7 +1478,7 @@ void SCI_METHOD LexerCPP::Fold(Sci_PositionU startPos, Sci_Position length, int
}
} else {
if ((ch == '/') && (chNext == '/')) {
char chNext2 = styler.SafeGetCharAt(i + 2);
const char chNext2 = styler.SafeGetCharAt(i + 2);
if (chNext2 == '{') {
levelNext++;
} else if (chNext2 == '}') {
@ -1433,6 +1577,7 @@ void LexerCPP::EvaluateTokens(std::vector<std::string> &tokens, const SymbolTabl
if (it != preprocessorDefinitions.end()) {
val = "1";
}
tokens.erase(tokens.begin() + i + 1, tokens.begin() + i + 2);
}
tokens[i] = val;
} else {
@ -1441,11 +1586,11 @@ void LexerCPP::EvaluateTokens(std::vector<std::string> &tokens, const SymbolTabl
}
// Evaluate identifiers
const size_t maxIterations = 100;
constexpr size_t maxIterations = 100;
size_t iterations = 0; // Limit number of iterations in case there is a recursive macro.
for (size_t i = 0; (i<tokens.size()) && (iterations < maxIterations);) {
iterations++;
if (setWordStart.Contains(static_cast<unsigned char>(tokens[i][0]))) {
if (setWordStart.Contains(tokens[i][0])) {
SymbolTable::const_iterator it = preprocessorDefinitions.find(tokens[i]);
if (it != preprocessorDefinitions.end()) {
// Tokenize value
@ -1472,7 +1617,7 @@ void LexerCPP::EvaluateTokens(std::vector<std::string> &tokens, const SymbolTabl
macroTokens.erase(std::remove_if(macroTokens.begin(), macroTokens.end(), OnlySpaceOrTab), macroTokens.end());
for (size_t iMacro = 0; iMacro < macroTokens.size();) {
if (setWordStart.Contains(static_cast<unsigned char>(macroTokens[iMacro][0]))) {
if (setWordStart.Contains(macroTokens[iMacro][0])) {
std::map<std::string, std::string>::const_iterator itFind = arguments.find(macroTokens[iMacro]);
if (itFind != arguments.end()) {
// TODO: Possible that value will be expression so should insert tokenized form
@ -1495,8 +1640,8 @@ void LexerCPP::EvaluateTokens(std::vector<std::string> &tokens, const SymbolTabl
tokens.insert(tokens.begin() + i, macroTokens.begin(), macroTokens.end());
}
} else {
// Identifier not found
tokens.erase(tokens.begin() + i);
// Identifier not found and value defaults to zero
tokens[i] = "0";
}
} else {
i++;
@ -1533,18 +1678,20 @@ void LexerCPP::EvaluateTokens(std::vector<std::string> &tokens, const SymbolTabl
}
// Evaluate expressions in precedence order
enum precedence { precArithmetic, precRelative, precLogical };
for (int prec=precArithmetic; prec <= precLogical; prec++) {
enum precedence { precMult, precAdd, precRelative
, precLogical, /* end marker */ precLast };
for (int prec = precMult; prec < precLast; prec++) {
// Looking at 3 tokens at a time so end at 2 before end
for (size_t k=0; (k+2)<tokens.size();) {
char chOp = tokens[k+1][0];
const char chOp = tokens[k+1][0];
if (
((prec==precArithmetic) && setArithmethicOp.Contains(chOp)) ||
((prec==precMult) && setMultOp.Contains(chOp)) ||
((prec==precAdd) && setAddOp.Contains(chOp)) ||
((prec==precRelative) && setRelOp.Contains(chOp)) ||
((prec==precLogical) && setLogicalOp.Contains(chOp))
) {
int valA = atoi(tokens[k].c_str());
int valB = atoi(tokens[k+2].c_str());
const int valA = atoi(tokens[k].c_str());
const int valB = atoi(tokens[k+2].c_str());
int result = 0;
if (tokens[k+1] == "+")
result = valA + valB;
@ -1572,11 +1719,9 @@ void LexerCPP::EvaluateTokens(std::vector<std::string> &tokens, const SymbolTabl
result = valA || valB;
else if (tokens[k+1] == "&&")
result = valA && valB;
char sResult[30];
sprintf(sResult, "%d", result);
std::vector<std::string>::iterator itInsert =
tokens.erase(tokens.begin() + k, tokens.begin() + k + 3);
tokens.insert(itInsert, sResult);
tokens.insert(itInsert, std::to_string(result));
} else {
k++;
}
@ -1590,9 +1735,9 @@ std::vector<std::string> LexerCPP::Tokenize(const std::string &expr) const {
const char *cp = expr.c_str();
while (*cp) {
std::string word;
if (setWord.Contains(static_cast<unsigned char>(*cp))) {
if (setWord.Contains(*cp)) {
// Identifiers and numbers
while (setWord.Contains(static_cast<unsigned char>(*cp))) {
while (setWord.Contains(*cp)) {
word += *cp;
cp++;
}
@ -1601,17 +1746,17 @@ std::vector<std::string> LexerCPP::Tokenize(const std::string &expr) const {
word += *cp;
cp++;
}
} else if (setRelOp.Contains(static_cast<unsigned char>(*cp))) {
} else if (setRelOp.Contains(*cp)) {
word += *cp;
cp++;
if (setRelOp.Contains(static_cast<unsigned char>(*cp))) {
if (setRelOp.Contains(*cp)) {
word += *cp;
cp++;
}
} else if (setLogicalOp.Contains(static_cast<unsigned char>(*cp))) {
} else if (setLogicalOp.Contains(*cp)) {
word += *cp;
cp++;
if (setLogicalOp.Contains(static_cast<unsigned char>(*cp))) {
if (setLogicalOp.Contains(*cp)) {
word += *cp;
cp++;
}
@ -1631,7 +1776,7 @@ bool LexerCPP::EvaluateExpression(const std::string &expr, const SymbolTable &pr
EvaluateTokens(tokens, preprocessorDefinitions);
// "0" or "" -> false else true
bool isFalse = tokens.empty() ||
const bool isFalse = tokens.empty() ||
((tokens.size() == 1) && ((tokens[0] == "") || tokens[0] == "0"));
return !isFalse;
}

View file

@ -1,7 +1,8 @@
// Scintilla source code edit control
// Encoding: UTF-8
/** @file LexCSS.cxx
** Lexer for Cascading Style Sheets
** Written by Jakub Vrána
** Written by Jakub Vrána
** Improved by Philippe Lhoste (CSS2)
** Improved by Ross McKay (SCSS mode; see http://sass-lang.com/ )
**/
@ -31,9 +32,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsAWordChar(const unsigned int ch) {
@ -347,6 +346,7 @@ static void ColouriseCssDoc(Sci_PositionU startPos, Sci_Position length, int ini
case SCE_CSS_DEFAULT:
if (isLessDocument) // give priority to pseudo elements
break;
// Falls through.
case SCE_CSS_VALUE:
lastStateVar = sc.state;
sc.SetState(SCE_CSS_VARIABLE);

View file

@ -37,6 +37,10 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wcomma"
#endif
// Since the Microsoft __iscsym[f] funcs are not ANSI...
inline int iscaml(int c) {return isalnum(c) || c == '_';}
inline int iscamlf(int c) {return isalpha(c) || c == '_';}
@ -46,9 +50,7 @@ static const int baseT[24] = {
0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0,16 /* M - X */
};
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
#ifdef BUILD_AS_EXTERNAL_LEXER
/*
@ -368,6 +370,7 @@ void ColouriseCamlDoc(
break;
}/* else
// fall through for SML char literal (handle like string) */
// Falls through.
case SCE_CAML_STRING:
// [try to] interpret as [additional] [SML char/] string literal char

View file

@ -24,9 +24,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static bool isCmakeNumber(char ch)
{
@ -87,10 +85,11 @@ static int calculateFoldCmake(Sci_PositionU start, Sci_PositionU end, int foldle
if ( CompareCaseInsensitive(s, "IF") == 0 || CompareCaseInsensitive(s, "WHILE") == 0
|| CompareCaseInsensitive(s, "MACRO") == 0 || CompareCaseInsensitive(s, "FOREACH") == 0
|| CompareCaseInsensitive(s, "ELSEIF") == 0 )
|| CompareCaseInsensitive(s, "FUNCTION") == 0 || CompareCaseInsensitive(s, "ELSEIF") == 0)
newFoldlevel++;
else if ( CompareCaseInsensitive(s, "ENDIF") == 0 || CompareCaseInsensitive(s, "ENDWHILE") == 0
|| CompareCaseInsensitive(s, "ENDMACRO") == 0 || CompareCaseInsensitive(s, "ENDFOREACH") == 0)
|| CompareCaseInsensitive(s, "ENDMACRO") == 0 || CompareCaseInsensitive(s, "ENDFOREACH") == 0
|| CompareCaseInsensitive(s, "ENDFUNCTION") == 0)
newFoldlevel--;
else if ( bElse && CompareCaseInsensitive(s, "ELSEIF") == 0 )
newFoldlevel++;

View file

@ -14,7 +14,8 @@
#include <assert.h>
#include <ctype.h>
#include "Platform.h"
#include <algorithm>
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
@ -26,9 +27,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static bool IsSpaceEquiv(int state) {
return (state == SCE_COFFEESCRIPT_DEFAULT
@ -427,7 +426,7 @@ static void FoldCoffeeScriptDoc(Sci_PositionU startPos, Sci_Position length, int
}
const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK;
const int levelBeforeComments = Platform::Maximum(indentCurrentLevel,levelAfterComments);
const int levelBeforeComments = std::max(indentCurrentLevel,levelAfterComments);
// Now set all the indent levels on the lines we skipped
// Do this from end to start. Once we encounter one line

View file

@ -27,9 +27,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static void ColouriseConfDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *keywordLists[], Accessor &styler)
{

View file

@ -25,9 +25,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static void ColouriseNncrontabDoc(Sci_PositionU startPos, Sci_Position length, int, WordList
*keywordLists[], Accessor &styler)

View file

@ -24,9 +24,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsAWordChar(const int ch) {
return (ch < 0x80) && (isalnum(ch) || ch == '.' ||

View file

@ -27,10 +27,9 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"
#include "DefaultLexer.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
/* Nested comments require keeping the value of the nesting level for every
position in the document. But since scintilla always styles line by line,
@ -145,7 +144,7 @@ struct OptionSetD : public OptionSet<OptionsD> {
}
};
class LexerD : public ILexer {
class LexerD : public DefaultLexer {
bool caseSensitive;
WordList keywords;
WordList keywords2;
@ -158,34 +157,38 @@ class LexerD : public ILexer {
OptionSetD osD;
public:
LexerD(bool caseSensitive_) :
DefaultLexer("D", SCLEX_D),
caseSensitive(caseSensitive_) {
}
virtual ~LexerD() {
}
void SCI_METHOD Release() {
void SCI_METHOD Release() override {
delete this;
}
int SCI_METHOD Version() const {
return lvOriginal;
int SCI_METHOD Version() const override {
return lvIdentity;
}
const char * SCI_METHOD PropertyNames() {
const char * SCI_METHOD PropertyNames() override {
return osD.PropertyNames();
}
int SCI_METHOD PropertyType(const char *name) {
int SCI_METHOD PropertyType(const char *name) override {
return osD.PropertyType(name);
}
const char * SCI_METHOD DescribeProperty(const char *name) {
const char * SCI_METHOD DescribeProperty(const char *name) override {
return osD.DescribeProperty(name);
}
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val);
const char * SCI_METHOD DescribeWordListSets() {
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
const char * SCI_METHOD PropertyGet(const char *key) override {
return osD.PropertyGet(key);
}
const char * SCI_METHOD DescribeWordListSets() override {
return osD.DescribeWordListSets();
}
Sci_Position SCI_METHOD WordListSet(int n, const char *wl);
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess);
void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess);
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 *) {
void * SCI_METHOD PrivateCall(int, void *) override {
return 0;
}

View file

@ -25,9 +25,7 @@
#include "LexerModule.h"
/***************************************/
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
/***********************************************/
static inline bool IsAWordChar(const int ch) {

View file

@ -21,10 +21,9 @@
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
#include "DefaultLexer.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static const char *const DMISWordListDesc[] = {
@ -38,7 +37,7 @@ static const char *const DMISWordListDesc[] = {
};
class LexerDMIS : public ILexer
class LexerDMIS : public DefaultLexer
{
private:
char *m_wordListSets;
@ -56,33 +55,37 @@ class LexerDMIS : public ILexer
LexerDMIS(void);
virtual ~LexerDMIS(void);
int SCI_METHOD Version() const {
return lvOriginal;
int SCI_METHOD Version() const override {
return lvIdentity;
}
void SCI_METHOD Release() {
void SCI_METHOD Release() override {
delete this;
}
const char * SCI_METHOD PropertyNames() {
const char * SCI_METHOD PropertyNames() override {
return NULL;
}
int SCI_METHOD PropertyType(const char *) {
int SCI_METHOD PropertyType(const char *) override {
return -1;
}
const char * SCI_METHOD DescribeProperty(const char *) {
const char * SCI_METHOD DescribeProperty(const char *) override {
return NULL;
}
Sci_Position SCI_METHOD PropertySet(const char *, const char *) {
Sci_Position SCI_METHOD PropertySet(const char *, const char *) override {
return -1;
}
Sci_Position SCI_METHOD WordListSet(int n, const char *wl);
const char * SCI_METHOD PropertyGet(const char *) override {
return NULL;
}
void * SCI_METHOD PrivateCall(int, void *) {
Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override;
void * SCI_METHOD PrivateCall(int, void *) override {
return NULL;
}
@ -90,9 +93,9 @@ class LexerDMIS : public ILexer
return new LexerDMIS;
}
const char * SCI_METHOD DescribeWordListSets();
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, IDocument *pAccess);
void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, IDocument *pAccess);
const char * SCI_METHOD DescribeWordListSets() 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;
};
@ -130,7 +133,7 @@ void SCI_METHOD LexerDMIS::InitWordListSets(void)
}
LexerDMIS::LexerDMIS(void) {
LexerDMIS::LexerDMIS(void) : DefaultLexer("DMIS", SCLEX_DMIS) {
this->InitWordListSets();
this->m_majorWords.Clear();

View file

@ -0,0 +1,614 @@
// Scintilla source code edit control
/** @file LexDataflex.cxx
** Lexer for DataFlex.
** Based on LexPascal.cxx
** Written by Wil van Antwerpen, June 2019
**/
/*
// The License.txt file describes the conditions under which this software may be distributed.
A few words about features of LexDataflex...
Generally speaking LexDataflex tries to support all available DataFlex features (up
to DataFlex 19.1 at this time).
~ FOLDING:
Folding is supported in the following cases:
- Folding of stream-like comments
- Folding of groups of consecutive line comments
- Folding of preprocessor blocks (the following preprocessor blocks are
supported: #IFDEF, #IFNDEF, #ENDIF and #HEADER / #ENDHEADER
blocks),
- Folding of code blocks on appropriate keywords (the following code blocks are
supported: "begin, struct, type, case / end" blocks, class & object
declarations and interface declarations)
Remarks:
- We pass 4 arrays to the lexer:
1. The DataFlex keyword list, these are normal DataFlex keywords
2. The Scope Open list, for example, begin / procedure / while
3. The Scope Close list, for example, end / end_procedure / loop
4. Operator list, for ex. + / - / * / Lt / iand
These lists are all mutually exclusive, scope open words should not be in the keyword list and vice versa
- Folding of code blocks tries to handle all special cases in which folding
should not occur.
~ KEYWORDS:
The list of keywords that can be used in dataflex.properties file (up to DataFlex
19.1):
- Keywords: .. snipped .. see dataflex.properties file.
*/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
#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"
using namespace Scintilla;
static void GetRangeLowered(Sci_PositionU start,
Sci_PositionU end,
Accessor &styler,
char *s,
Sci_PositionU len) {
Sci_PositionU i = 0;
while ((i < end - start + 1) && (i < len-1)) {
s[i] = static_cast<char>(tolower(styler[start + i]));
i++;
}
s[i] = '\0';
}
static void GetForwardRangeLowered(Sci_PositionU start,
CharacterSet &charSet,
Accessor &styler,
char *s,
Sci_PositionU len) {
Sci_PositionU i = 0;
while ((i < len-1) && charSet.Contains(styler.SafeGetCharAt(start + i))) {
s[i] = static_cast<char>(tolower(styler.SafeGetCharAt(start + i)));
i++;
}
s[i] = '\0';
}
enum {
stateInICode = 0x1000,
stateSingleQuoteOpen = 0x2000,
stateDoubleQuoteOpen = 0x4000,
stateFoldInPreprocessor = 0x0100,
stateFoldInCaseStatement = 0x0200,
stateFoldInPreprocessorLevelMask = 0x00FF,
stateFoldMaskAll = 0x0FFF
};
static bool IsFirstDataFlexWord(Sci_Position pos, Accessor &styler) {
Sci_Position line = styler.GetLine(pos);
Sci_Position start_pos = styler.LineStart(line);
for (Sci_Position i = start_pos; i < pos; i++) {
char ch = styler.SafeGetCharAt(i);
if (!(ch == ' ' || ch == '\t'))
return false;
}
return true;
}
inline bool IsADataFlexField(int ch) {
return (ch == '.');
}
size_t _strnlen(const char *s, size_t max) {
const char *end = (const char*)memchr((void *)s, 0, max);
return end ? (size_t)(end - s) : max;
}
static void ClassifyDataFlexWord(WordList *keywordlists[], StyleContext &sc, Accessor &styler) {
WordList& keywords = *keywordlists[0];
WordList& scopeOpen = *keywordlists[1];
WordList& scopeClosed = *keywordlists[2];
WordList& operators = *keywordlists[3];
char s[100];
int oldState;
int newState;
size_t tokenlen;
oldState = sc.state;
newState = oldState;
sc.GetCurrentLowered(s, sizeof(s));
tokenlen = _strnlen(s,sizeof(s));
if (keywords.InList(s)) {
// keywords in DataFlex can be used as table column names (file.field) and as such they
// should not be characterized as a keyword. So test for that.
// for ex. somebody using date as field name.
if (!IsADataFlexField(sc.GetRelative(-static_cast<int>(tokenlen+1)))) {
newState = SCE_DF_WORD;
}
}
if (oldState == newState) {
if ((scopeOpen.InList(s) || scopeClosed.InList(s)) && (strcmp(s, "for") != 0) && (strcmp(s, "repeat") != 0)) {
// scope words in DataFlex can be used as table column names (file.field) and as such they
// should not be characterized as a scope word. So test for that.
// for ex. somebody using procedure for field name.
if (!IsADataFlexField(sc.GetRelative(-static_cast<int>(tokenlen+1)))) {
newState = SCE_DF_SCOPEWORD;
}
}
// no code folding on the next words, but just want to paint them like keywords (as they are) (??? doesn't the code to the opposite?)
if (strcmp(s, "if") == 0 ||
strcmp(s, "ifnot") == 0 ||
strcmp(s, "case") == 0 ||
strcmp(s, "else") == 0 ) {
newState = SCE_DF_SCOPEWORD;
}
}
if (oldState != newState && newState == SCE_DF_WORD) {
// a for loop must have for at the start of the line, for is also used in "define abc for 123"
if ( (strcmp(s, "for") == 0) && (IsFirstDataFlexWord(sc.currentPos-3, styler)) ) {
newState = SCE_DF_SCOPEWORD;
}
}
if (oldState != newState && newState == SCE_DF_WORD) {
// a repeat loop must have repeat at the start of the line, repeat is also used in 'move (repeat("d",5)) to sFoo'
if ( (strcmp(s, "repeat") == 0) && (IsFirstDataFlexWord(sc.currentPos-6, styler)) ) {
newState = SCE_DF_SCOPEWORD;
}
}
if (oldState == newState) {
if (operators.InList(s)) {
newState = SCE_DF_OPERATOR;
}
}
if (oldState != newState) {
sc.ChangeState(newState);
}
sc.SetState(SCE_DF_DEFAULT);
}
static void ColouriseDataFlexDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[],
Accessor &styler) {
// bool bSmartHighlighting = styler.GetPropertyInt("lexer.dataflex.smart.highlighting", 1) != 0;
CharacterSet setWordStart(CharacterSet::setAlpha, "_$#@", 0x80, true);
CharacterSet setWord(CharacterSet::setAlphaNum, "_$#@", 0x80, true);
CharacterSet setNumber(CharacterSet::setDigits, ".-+eE");
CharacterSet setHexNumber(CharacterSet::setDigits, "abcdefABCDEF");
CharacterSet setOperator(CharacterSet::setNone, "*+-/<=>^");
Sci_Position curLine = styler.GetLine(startPos);
int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : 0;
StyleContext sc(startPos, length, initStyle, styler);
for (; sc.More(); sc.Forward()) {
if (sc.atLineEnd) {
// Update the line state, so it can be seen by next line
curLine = styler.GetLine(sc.currentPos);
styler.SetLineState(curLine, curLineState);
}
// Determine if the current state should terminate.
switch (sc.state) {
case SCE_DF_NUMBER:
if (!setNumber.Contains(sc.ch) || (sc.ch == '.' && sc.chNext == '.')) {
sc.SetState(SCE_DF_DEFAULT);
} else if (sc.ch == '-' || sc.ch == '+') {
if (sc.chPrev != 'E' && sc.chPrev != 'e') {
sc.SetState(SCE_DF_DEFAULT);
}
}
break;
case SCE_DF_IDENTIFIER:
if (!setWord.Contains(sc.ch)) {
ClassifyDataFlexWord(keywordlists, sc, styler);
}
break;
case SCE_DF_HEXNUMBER:
if (!(setHexNumber.Contains(sc.ch) || sc.ch == 'I') ) { // in |CI$22a we also want to color the "I"
sc.SetState(SCE_DF_DEFAULT);
}
break;
case SCE_DF_METATAG:
if (sc.atLineStart || sc.chPrev == '}') {
sc.SetState(SCE_DF_DEFAULT);
}
break;
case SCE_DF_PREPROCESSOR:
if (sc.atLineStart || IsASpaceOrTab(sc.ch)) {
sc.SetState(SCE_DF_DEFAULT);
}
break;
case SCE_DF_IMAGE:
if (sc.atLineStart && sc.Match("/*")) {
sc.Forward(); // these characters are still part of the DF Image
sc.ForwardSetState(SCE_DF_DEFAULT);
}
break;
case SCE_DF_PREPROCESSOR2:
// we don't have inline comments or preprocessor2 commands
//if (sc.Match('*', ')')) {
// sc.Forward();
// sc.ForwardSetState(SCE_DF_DEFAULT);
//}
break;
case SCE_DF_COMMENTLINE:
if (sc.atLineStart) {
sc.SetState(SCE_DF_DEFAULT);
}
break;
case SCE_DF_STRING:
if (sc.atLineEnd) {
sc.ChangeState(SCE_DF_STRINGEOL);
} else if (sc.ch == '\'' && sc.chNext == '\'') {
sc.Forward();
} else if (sc.ch == '\"' && sc.chNext == '\"') {
sc.Forward();
} else if (sc.ch == '\'' || sc.ch == '\"') {
if (sc.ch == '\'' && (curLineState & stateSingleQuoteOpen) ) {
curLineState &= ~(stateSingleQuoteOpen);
sc.ForwardSetState(SCE_DF_DEFAULT);
}
else if (sc.ch == '\"' && (curLineState & stateDoubleQuoteOpen) ) {
curLineState &= ~(stateDoubleQuoteOpen);
sc.ForwardSetState(SCE_DF_DEFAULT);
}
}
break;
case SCE_DF_STRINGEOL:
if (sc.atLineStart) {
sc.SetState(SCE_DF_DEFAULT);
}
break;
case SCE_DF_SCOPEWORD:
//if (!setHexNumber.Contains(sc.ch) && sc.ch != '$') {
// sc.SetState(SCE_DF_DEFAULT);
//}
break;
case SCE_DF_OPERATOR:
// if (bSmartHighlighting && sc.chPrev == ';') {
// curLineState &= ~(stateInProperty | stateInExport);
// }
sc.SetState(SCE_DF_DEFAULT);
break;
case SCE_DF_ICODE:
if (sc.atLineStart || IsASpace(sc.ch) || isoperator(sc.ch)) {
sc.SetState(SCE_DF_DEFAULT);
}
break;
}
// Determine if a new state should be entered.
if (sc.state == SCE_DF_DEFAULT) {
if (IsADigit(sc.ch)) {
sc.SetState(SCE_DF_NUMBER);
} else if (sc.Match('/', '/') || sc.Match("#REM")) {
sc.SetState(SCE_DF_COMMENTLINE);
} else if ((sc.ch == '#' && !sc.Match("#REM")) && IsFirstDataFlexWord(sc.currentPos, styler)) {
sc.SetState(SCE_DF_PREPROCESSOR);
// || (sc.ch == '|' && sc.chNext == 'C' && sc.GetRelativeCharacter(2) == 'I' && sc.GetRelativeCharacter(3) == '$') ) {
} else if ((sc.ch == '$' && ((!setWord.Contains(sc.chPrev)) || sc.chPrev == 'I' ) ) || (sc.Match("|CI$")) ) {
sc.SetState(SCE_DF_HEXNUMBER); // start with $ and previous character not in a..zA..Z0..9 excluding "I" OR start with |CI$
} else if (setWordStart.Contains(sc.ch)) {
sc.SetState(SCE_DF_IDENTIFIER);
} else if (sc.ch == '{') {
sc.SetState(SCE_DF_METATAG);
//} else if (sc.Match("(*$")) {
// sc.SetState(SCE_DF_PREPROCESSOR2);
} else if (sc.ch == '/' && setWord.Contains(sc.chNext) && sc.atLineStart) {
sc.SetState(SCE_DF_IMAGE);
// sc.Forward(); // Eat the * so it isn't used for the end of the comment
} else if (sc.ch == '\'' || sc.ch == '\"') {
if (sc.ch == '\'' && !(curLineState & stateDoubleQuoteOpen)) {
curLineState |= stateSingleQuoteOpen;
} else if (sc.ch == '\"' && !(curLineState & stateSingleQuoteOpen)) {
curLineState |= stateDoubleQuoteOpen;
}
sc.SetState(SCE_DF_STRING);
} else if (setOperator.Contains(sc.ch)) {
sc.SetState(SCE_DF_OPERATOR);
// } else if (curLineState & stateInICode) {
// ICode start ! in a string followed by close string mark is not icode
} else if ((sc.ch == '!') && !(sc.ch == '!' && ((sc.chNext == '\"') || (sc.ch == '\'')) )) {
sc.SetState(SCE_DF_ICODE);
}
}
}
if (sc.state == SCE_DF_IDENTIFIER && setWord.Contains(sc.chPrev)) {
ClassifyDataFlexWord(keywordlists, sc, styler);
}
sc.Complete();
}
static bool IsStreamCommentStyle(int style) {
return style == SCE_DF_IMAGE;
}
static bool IsCommentLine(Sci_Position line, Accessor &styler) {
Sci_Position pos = styler.LineStart(line);
Sci_Position eolPos = styler.LineStart(line + 1) - 1;
for (Sci_Position i = pos; i < eolPos; i++) {
char ch = styler[i];
char chNext = styler.SafeGetCharAt(i + 1);
int style = styler.StyleAt(i);
if (ch == '/' && chNext == '/' && style == SCE_DF_COMMENTLINE) {
return true;
} else if (!IsASpaceOrTab(ch)) {
return false;
}
}
return false;
}
static unsigned int GetFoldInPreprocessorLevelFlag(int lineFoldStateCurrent) {
return lineFoldStateCurrent & stateFoldInPreprocessorLevelMask;
}
static void SetFoldInPreprocessorLevelFlag(int &lineFoldStateCurrent, unsigned int nestLevel) {
lineFoldStateCurrent &= ~stateFoldInPreprocessorLevelMask;
lineFoldStateCurrent |= nestLevel & stateFoldInPreprocessorLevelMask;
}
static int ClassifyDataFlexPreprocessorFoldPoint(int &levelCurrent, int &lineFoldStateCurrent,
Sci_PositionU startPos, Accessor &styler) {
CharacterSet setWord(CharacterSet::setAlpha);
char s[100]; // Size of the longest possible keyword + one additional character + null
GetForwardRangeLowered(startPos, setWord, styler, s, sizeof(s));
size_t iLen = _strnlen(s,sizeof(s));
size_t iWordSize = 0;
unsigned int nestLevel = GetFoldInPreprocessorLevelFlag(lineFoldStateCurrent);
if (strcmp(s, "command") == 0 ||
// The #if/#ifdef etcetera commands are not currently foldable as it is easy to write code that
// breaks the collaps logic, so we keep things simple and not include that for now.
strcmp(s, "header") == 0) {
nestLevel++;
SetFoldInPreprocessorLevelFlag(lineFoldStateCurrent, nestLevel);
lineFoldStateCurrent |= stateFoldInPreprocessor;
levelCurrent++;
iWordSize = iLen;
} else if (strcmp(s, "endcommand") == 0 ||
strcmp(s, "endheader") == 0) {
nestLevel--;
SetFoldInPreprocessorLevelFlag(lineFoldStateCurrent, nestLevel);
if (nestLevel == 0) {
lineFoldStateCurrent &= ~stateFoldInPreprocessor;
}
levelCurrent--;
iWordSize = iLen;
if (levelCurrent < SC_FOLDLEVELBASE) {
levelCurrent = SC_FOLDLEVELBASE;
}
}
return static_cast<int>(iWordSize);
}
static void ClassifyDataFlexWordFoldPoint(int &levelCurrent, int &lineFoldStateCurrent,
Sci_PositionU lastStart, Sci_PositionU currentPos, WordList *[], Accessor &styler) {
char s[100];
// property fold.dataflex.compilerlist
// Set to 1 for enabling the code folding feature in *.prn files
bool foldPRN = styler.GetPropertyInt("fold.dataflex.compilerlist",0) != 0;
GetRangeLowered(lastStart, currentPos, styler, s, sizeof(s));
if (strcmp(s, "case") == 0) {
lineFoldStateCurrent |= stateFoldInCaseStatement;
} else if (strcmp(s, "begin") == 0) {
levelCurrent++;
} else if (strcmp(s, "for") == 0 ||
strcmp(s, "while") == 0 ||
strcmp(s, "repeat") == 0 ||
strcmp(s, "for_all") == 0 ||
strcmp(s, "struct") == 0 ||
strcmp(s, "type") == 0 ||
strcmp(s, "begin_row") == 0 ||
strcmp(s, "item_list") == 0 ||
strcmp(s, "begin_constraints") == 0 ||
strcmp(s, "begin_transaction") == 0 ||
strcmp(s, "enum_list") == 0 ||
strcmp(s, "class") == 0 ||
strcmp(s, "object") == 0 ||
strcmp(s, "cd_popup_object") == 0 ||
strcmp(s, "procedure") == 0 ||
strcmp(s, "procedure_section") == 0 ||
strcmp(s, "function") == 0 ) {
if ((IsFirstDataFlexWord(lastStart, styler )) || foldPRN) {
levelCurrent++;
}
} else if (strcmp(s, "end") == 0) { // end is not always the first keyword, for example "case end"
levelCurrent--;
if (levelCurrent < SC_FOLDLEVELBASE) {
levelCurrent = SC_FOLDLEVELBASE;
}
} else if (strcmp(s, "loop") == 0 ||
strcmp(s, "until") == 0 ||
strcmp(s, "end_class") == 0 ||
strcmp(s, "end_object") == 0 ||
strcmp(s, "cd_end_object") == 0 ||
strcmp(s, "end_procedure") == 0 ||
strcmp(s, "end_function") == 0 ||
strcmp(s, "end_for_all") == 0 ||
strcmp(s, "end_struct") == 0 ||
strcmp(s, "end_type") == 0 ||
strcmp(s, "end_row") == 0 ||
strcmp(s, "end_item_list") == 0 ||
strcmp(s, "end_constraints") == 0 ||
strcmp(s, "end_transaction") == 0 ||
strcmp(s, "end_enum_list") == 0 ) {
// lineFoldStateCurrent &= ~stateFoldInRecord;
if ((IsFirstDataFlexWord(lastStart, styler )) || foldPRN) {
levelCurrent--;
if (levelCurrent < SC_FOLDLEVELBASE) {
levelCurrent = SC_FOLDLEVELBASE;
}
}
}
}
static void ClassifyDataFlexMetaDataFoldPoint(int &levelCurrent,
Sci_PositionU lastStart, Sci_PositionU currentPos, WordList *[], Accessor &styler) {
char s[100];
GetRangeLowered(lastStart, currentPos, styler, s, sizeof(s));
if (strcmp(s, "#beginsection") == 0) {
levelCurrent++;
} else if (strcmp(s, "#endsection") == 0) {
levelCurrent--;
if (levelCurrent < SC_FOLDLEVELBASE) {
levelCurrent = SC_FOLDLEVELBASE;
}
}
}
static void FoldDataFlexDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[],
Accessor &styler) {
bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
Sci_PositionU endPos = startPos + length;
int visibleChars = 0;
Sci_Position lineCurrent = styler.GetLine(startPos);
int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
int levelCurrent = levelPrev;
int lineFoldStateCurrent = lineCurrent > 0 ? styler.GetLineState(lineCurrent - 1) & stateFoldMaskAll : 0;
char chNext = styler[startPos];
int styleNext = styler.StyleAt(startPos);
int style = initStyle;
int iWordSize;
Sci_Position lastStart = 0;
CharacterSet setWord(CharacterSet::setAlphaNum, "_$#@", 0x80, true);
for (Sci_PositionU i = startPos; i < endPos; i++) {
char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
int stylePrev = style;
style = styleNext;
styleNext = styler.StyleAt(i + 1);
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
if (foldComment && IsStreamCommentStyle(style)) {
if (!IsStreamCommentStyle(stylePrev)) {
levelCurrent++;
} else if (!IsStreamCommentStyle(styleNext)) {
levelCurrent--;
}
}
if (foldComment && atEOL && IsCommentLine(lineCurrent, styler))
{
if (!IsCommentLine(lineCurrent - 1, styler)
&& IsCommentLine(lineCurrent + 1, styler))
levelCurrent++;
else if (IsCommentLine(lineCurrent - 1, styler)
&& !IsCommentLine(lineCurrent+1, styler))
levelCurrent--;
}
if (foldPreprocessor) {
if (style == SCE_DF_PREPROCESSOR) {
iWordSize = ClassifyDataFlexPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 1, styler);
//} else if (style == SCE_DF_PREPROCESSOR2 && ch == '(' && chNext == '*'
// && styler.SafeGetCharAt(i + 2) == '$') {
// ClassifyDataFlexPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 3, styler);
i = i + iWordSize;
}
}
if (stylePrev != SCE_DF_SCOPEWORD && style == SCE_DF_SCOPEWORD)
{
// Store last word start point.
lastStart = i;
}
if (stylePrev == SCE_DF_SCOPEWORD) {
if(setWord.Contains(ch) && !setWord.Contains(chNext)) {
ClassifyDataFlexWordFoldPoint(levelCurrent, lineFoldStateCurrent, lastStart, i, keywordlists, styler);
}
}
if (stylePrev == SCE_DF_METATAG && ch == '#')
{
// Store last word start point.
lastStart = i;
}
if (stylePrev == SCE_DF_METATAG) {
if(setWord.Contains(ch) && !setWord.Contains(chNext)) {
ClassifyDataFlexMetaDataFoldPoint(levelCurrent, lastStart, i, keywordlists, styler);
}
}
if (!IsASpace(ch))
visibleChars++;
if (atEOL) {
int lev = levelPrev;
if (visibleChars == 0 && foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG;
if ((levelCurrent > levelPrev) && (visibleChars > 0))
lev |= SC_FOLDLEVELHEADERFLAG;
if (lev != styler.LevelAt(lineCurrent)) {
styler.SetLevel(lineCurrent, lev);
}
int newLineState = (styler.GetLineState(lineCurrent) & ~stateFoldMaskAll) | lineFoldStateCurrent;
styler.SetLineState(lineCurrent, newLineState);
lineCurrent++;
levelPrev = levelCurrent;
visibleChars = 0;
}
}
// If we didn't reach the EOL in previous loop, store line level and whitespace information.
// The rest will be filled in later...
int lev = levelPrev;
if (visibleChars == 0 && foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG;
styler.SetLevel(lineCurrent, lev);
}
static const char * const dataflexWordListDesc[] = {
"Keywords",
"Scope open",
"Scope close",
"Operators",
0
};
LexerModule lmDataflex(SCLEX_DATAFLEX, ColouriseDataFlexDoc, "dataflex", FoldDataFlexDoc, dataflexWordListDesc);

View file

@ -23,9 +23,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool AtEOL(Accessor &styler, Sci_PositionU i) {
return (styler[i] == '\n') ||
@ -51,8 +49,10 @@ static void ColouriseDiffLine(char *lineBuffer, Sci_Position endLine, Accessor &
styler.ColourTo(endLine, SCE_DIFF_POSITION);
else if (lineBuffer[3] == '\r' || lineBuffer[3] == '\n')
styler.ColourTo(endLine, SCE_DIFF_POSITION);
else
else if (lineBuffer[3] == ' ')
styler.ColourTo(endLine, SCE_DIFF_HEADER);
else
styler.ColourTo(endLine, SCE_DIFF_DELETED);
} else if (0 == strncmp(lineBuffer, "+++ ", 4)) {
// I don't know of any diff where "+++ " is a position marker, but for
// consistency, do the same as with "--- " and "*** ".
@ -78,6 +78,14 @@ static void ColouriseDiffLine(char *lineBuffer, Sci_Position endLine, Accessor &
styler.ColourTo(endLine, SCE_DIFF_POSITION);
} else if (lineBuffer[0] >= '0' && lineBuffer[0] <= '9') {
styler.ColourTo(endLine, SCE_DIFF_POSITION);
} else if (0 == strncmp(lineBuffer, "++", 2)) {
styler.ColourTo(endLine, SCE_DIFF_PATCH_ADD);
} else if (0 == strncmp(lineBuffer, "+-", 2)) {
styler.ColourTo(endLine, SCE_DIFF_PATCH_DELETE);
} else if (0 == strncmp(lineBuffer, "-+", 2)) {
styler.ColourTo(endLine, SCE_DIFF_REMOVED_PATCH_ADD);
} else if (0 == strncmp(lineBuffer, "--", 2)) {
styler.ColourTo(endLine, SCE_DIFF_REMOVED_PATCH_DELETE);
} else if (lineBuffer[0] == '-' || lineBuffer[0] == '<') {
styler.ColourTo(endLine, SCE_DIFF_DELETED);
} else if (lineBuffer[0] == '+' || lineBuffer[0] == '>') {
@ -124,7 +132,7 @@ static void FoldDiffDoc(Sci_PositionU startPos, Sci_Position length, int, WordLi
int nextLevel;
do {
int lineType = styler.StyleAt(curLineStart);
const int lineType = styler.StyleAt(curLineStart);
if (lineType == SCE_DIFF_COMMAND)
nextLevel = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
else if (lineType == SCE_DIFF_HEADER)

View file

@ -42,9 +42,7 @@
#define SET_UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define SET_DIGITS "0123456789"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static bool IsSpaceEquiv(int state) {
switch (state) {

View file

@ -1,4 +1,5 @@
// Scintilla Lexer for EDIFACT
// @file LexEDIFACT.cxx
// Written by Iain Clarke, IMCSoft & Inobiz AB.
// EDIFACT documented here: https://www.unece.org/cefact/edifact/welcome.html
// and more readably here: https://en.wikipedia.org/wiki/EDIFACT
@ -12,18 +13,19 @@
#include <cstring>
#include <cctype>
#include <string>
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
#include "LexAccessor.h"
#include "LexerModule.h"
#include "DefaultLexer.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
class LexerEDIFACT : public ILexer
class LexerEDIFACT : public DefaultLexer
{
public:
LexerEDIFACT();
@ -33,48 +35,72 @@ public:
return new LexerEDIFACT;
}
virtual int SCI_METHOD Version() const
int SCI_METHOD Version() const override
{
return lvOriginal;
return lvIdentity;
}
virtual void SCI_METHOD Release()
void SCI_METHOD Release() override
{
delete this;
}
const char * SCI_METHOD PropertyNames()
const char * SCI_METHOD PropertyNames() override
{
return "fold";
return "fold\nlexer.edifact.highlight.un.all";
}
int SCI_METHOD PropertyType(const char *)
int SCI_METHOD PropertyType(const char *) override
{
return SC_TYPE_BOOLEAN; // Only one property!
}
const char * SCI_METHOD DescribeProperty(const char *name)
const char * SCI_METHOD DescribeProperty(const char *name) override
{
if (strcmp(name, "fold"))
return NULL;
return "Whether to apply folding to document or not";
if (!strcmp(name, "fold"))
return "Whether to apply folding to document or not";
if (!strcmp(name, "lexer.edifact.highlight.un.all"))
return "Whether to apply UN* highlighting to all UN segments, or just to UNH";
return NULL;
}
virtual Sci_Position SCI_METHOD PropertySet(const char *key, const char *val)
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override
{
if (strcmp(key, "fold"))
return -1;
m_bFold = strcmp(val, "0") ? true : false;
return 0;
if (!strcmp(key, "fold"))
{
m_bFold = strcmp(val, "0") ? true : false;
return 0;
}
if (!strcmp(key, "lexer.edifact.highlight.un.all")) // GetProperty
{
m_bHighlightAllUN = strcmp(val, "0") ? true : false;
return 0;
}
return -1;
}
const char * SCI_METHOD DescribeWordListSets()
const char * SCI_METHOD PropertyGet(const char *key) override
{
m_lastPropertyValue = "";
if (!strcmp(key, "fold"))
{
m_lastPropertyValue = m_bFold ? "1" : "0";
}
if (!strcmp(key, "lexer.edifact.highlight.un.all")) // GetProperty
{
m_lastPropertyValue = m_bHighlightAllUN ? "1" : "0";
}
return m_lastPropertyValue.c_str();
}
const char * SCI_METHOD DescribeWordListSets() override
{
return NULL;
}
virtual Sci_Position SCI_METHOD WordListSet(int, const char *)
Sci_Position SCI_METHOD WordListSet(int, const char *) override
{
return -1;
}
virtual void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, IDocument *pAccess);
virtual void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle, IDocument *pAccess);
virtual void * SCI_METHOD PrivateCall(int, void *)
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 NULL;
}
@ -86,11 +112,18 @@ protected:
int DetectSegmentHeader(char SegmentHeader[3]) const;
bool m_bFold;
// property lexer.edifact.highlight.un.all
// Set to 0 to highlight only UNA segments, or 1 to highlight all UNx segments.
bool m_bHighlightAllUN;
char m_chComponent;
char m_chData;
char m_chDecimal;
char m_chRelease;
char m_chSegment;
std::string m_lastPropertyValue;
};
LexerModule lmEDIFACT(SCLEX_EDIFACT, LexerEDIFACT::Factory, "edifact");
@ -101,9 +134,10 @@ LexerModule lmEDIFACT(SCLEX_EDIFACT, LexerEDIFACT::Factory, "edifact");
///////////////////////////////////////////////////////////////////////////////
LexerEDIFACT::LexerEDIFACT()
LexerEDIFACT::LexerEDIFACT() : DefaultLexer("edifact", SCLEX_EDIFACT)
{
m_bFold = false;
m_bHighlightAllUN = false;
m_chComponent = ':';
m_chData = '+';
m_chDecimal = '.';
@ -111,9 +145,9 @@ LexerEDIFACT::LexerEDIFACT()
m_chSegment = '\'';
}
void LexerEDIFACT::Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int, IDocument *pAccess)
void LexerEDIFACT::Lex(Sci_PositionU startPos, Sci_Position length, int, IDocument *pAccess)
{
Sci_PositionU posFinish = startPos + lengthDoc;
Sci_PositionU posFinish = startPos + length;
InitialiseFromUNA(pAccess, posFinish);
// Look backwards for a ' or a document beginning
@ -191,40 +225,85 @@ void LexerEDIFACT::Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int, IDoc
pAccess->SetStyleFor(posFinish - posSegmentStart, SCE_EDI_BADSEGMENT);
}
void LexerEDIFACT::Fold(Sci_PositionU startPos, Sci_Position lengthDoc, int, IDocument *pAccess)
void LexerEDIFACT::Fold(Sci_PositionU startPos, Sci_Position length, int, IDocument *pAccess)
{
if (!m_bFold)
return;
// Fold at UNx lines. ie, UNx segments = 0, other segments = 1.
// There's no sub folding, so we can be quite simple.
Sci_Position endPos = startPos + lengthDoc;
Sci_PositionU endPos = startPos + length;
startPos = FindPreviousEnd(pAccess, startPos);
char c;
char SegmentHeader[4] = { 0 };
int iIndentPrevious = 0;
Sci_Position lineLast = pAccess->LineFromPosition(endPos);
bool AwaitingSegment = true;
Sci_PositionU currLine = pAccess->LineFromPosition(startPos);
int levelCurrentStyle = SC_FOLDLEVELBASE;
if (currLine > 0)
levelCurrentStyle = pAccess->GetLevel(currLine - 1); // bottom 12 bits are level
int indentCurrent = levelCurrentStyle & SC_FOLDLEVELNUMBERMASK;
int indentNext = indentCurrent;
for (Sci_Position lineCurrent = pAccess->LineFromPosition(startPos); lineCurrent <= lineLast; lineCurrent++)
while (startPos < endPos)
{
Sci_Position posLineStart = pAccess->LineStart(lineCurrent);
posLineStart = ForwardPastWhitespace(pAccess, posLineStart, endPos);
Sci_Position lineDataStart = pAccess->LineFromPosition(posLineStart);
// Fill in whitespace lines?
for (; lineCurrent < lineDataStart; lineCurrent++)
pAccess->SetLevel(lineCurrent, SC_FOLDLEVELBASE | SC_FOLDLEVELWHITEFLAG | iIndentPrevious);
pAccess->GetCharRange(SegmentHeader, posLineStart, 3);
//if (DetectSegmentHeader(SegmentHeader) == SCE_EDI_BADSEGMENT) // Abort if this is not a proper segment header
pAccess->GetCharRange(&c, startPos, 1);
switch (c)
{
case '\t':
case '\r':
case ' ':
startPos++;
continue;
case '\n':
currLine = pAccess->LineFromPosition(startPos);
pAccess->SetLevel(currLine, levelCurrentStyle | indentCurrent);
startPos++;
levelCurrentStyle = SC_FOLDLEVELBASE;
indentCurrent = indentNext;
continue;
}
if (c == m_chRelease)
{
startPos += 2;
continue;
}
if (c == m_chSegment)
{
AwaitingSegment = true;
startPos++;
continue;
}
int level = 0;
if (memcmp(SegmentHeader, "UNH", 3) == 0) // UNH starts blocks
level = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
// Check for UNA,B and Z. All others are inside messages
else if (!memcmp(SegmentHeader, "UNA", 3) || !memcmp(SegmentHeader, "UNB", 3) || !memcmp(SegmentHeader, "UNZ", 3))
level = SC_FOLDLEVELBASE;
else
level = SC_FOLDLEVELBASE | 1;
pAccess->SetLevel(lineCurrent, level);
iIndentPrevious = level & SC_FOLDLEVELNUMBERMASK;
if (!AwaitingSegment)
{
startPos++;
continue;
}
// Segment!
pAccess->GetCharRange(SegmentHeader, startPos, 3);
if (SegmentHeader[0] != 'U' || SegmentHeader[1] != 'N')
{
startPos++;
continue;
}
AwaitingSegment = false;
switch (SegmentHeader[2])
{
case 'H':
case 'G':
indentNext++;
levelCurrentStyle = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
break;
case 'T':
case 'E':
if (indentNext > 0)
indentNext--;
break;
}
startPos += 3;
}
}
@ -295,9 +374,14 @@ int LexerEDIFACT::DetectSegmentHeader(char SegmentHeader[3]) const
SegmentHeader[2] < 'A' || SegmentHeader[2] > 'Z')
return SCE_EDI_BADSEGMENT;
if (memcmp(SegmentHeader, "UNA", 3) == 0)
if (!memcmp(SegmentHeader, "UNA", 3))
return SCE_EDI_UNA;
if (memcmp(SegmentHeader, "UNH", 3) == 0)
if (m_bHighlightAllUN && !memcmp(SegmentHeader, "UN", 2))
return SCE_EDI_UNH;
else if (!memcmp(SegmentHeader, "UNH", 3))
return SCE_EDI_UNH;
else if (!memcmp(SegmentHeader, "UNG", 3))
return SCE_EDI_UNH;
return SCE_EDI_SEGMENTSTART;
@ -315,3 +399,5 @@ Sci_Position LexerEDIFACT::FindPreviousEnd(IDocument *pAccess, Sci_Position star
// We didn't find a ', so just go with the beginning
return 0;
}

View file

@ -1,5 +1,5 @@
// Scintilla source code edit control
/** @file LexESCRIPT.cxx
/** @file LexEScript.cxx
** Lexer for ESCRIPT
**/
// Copyright 2003 by Patrizio Bekerle (patrizio@bekerle.com)
@ -22,9 +22,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsAWordChar(const int ch) {

View file

@ -23,9 +23,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool isEiffelOperator(unsigned int ch) {
// '.' left out as it is used to make up numbers

View file

@ -1,11 +1,12 @@
// Scintilla source code edit control
// Encoding: UTF-8
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
/** @file LexErlang.cxx
** Lexer for Erlang.
** Enhanced by Etienne 'Lenain' Girondel (lenaing@gmail.com)
** Originally wrote by Peter-Henry Mander,
** based on Matlab lexer by José Fonseca.
** based on Matlab lexer by José Fonseca.
**/
#include <stdlib.h>
@ -26,9 +27,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static int is_radix(int radix, int ch) {
int digit;
@ -116,6 +115,7 @@ static void ColouriseErlangDoc(Sci_PositionU startPos, Sci_Position length, int
}
}
// V--- Falling through!
// Falls through.
case COMMENT_FUNCTION : {
if (sc.ch != '%') {
to_late_to_comment = true;
@ -128,6 +128,7 @@ static void ColouriseErlangDoc(Sci_PositionU startPos, Sci_Position length, int
}
}
// V--- Falling through!
// Falls through.
case COMMENT_MODULE : {
if (parse_state != COMMENT) {
// Search for comment documentation

View file

@ -12,6 +12,8 @@
#include <assert.h>
#include <ctype.h>
#include <string>
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
@ -23,32 +25,45 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static bool strstart(const char *haystack, const char *needle) {
namespace {
bool strstart(const char *haystack, const char *needle) noexcept {
return strncmp(haystack, needle, strlen(needle)) == 0;
}
static bool Is0To9(char ch) {
constexpr bool Is0To9(char ch) noexcept {
return (ch >= '0') && (ch <= '9');
}
static bool Is1To9(char ch) {
constexpr bool Is1To9(char ch) noexcept {
return (ch >= '1') && (ch <= '9');
}
static bool IsAlphabetic(int ch) {
bool IsAlphabetic(int ch) {
return IsASCII(ch) && isalpha(ch);
}
static inline bool AtEOL(Accessor &styler, Sci_PositionU i) {
inline bool AtEOL(Accessor &styler, Sci_PositionU i) {
return (styler[i] == '\n') ||
((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
}
static int RecogniseErrorListLine(const char *lineBuffer, Sci_PositionU lengthLine, Sci_Position &startValue) {
bool IsGccExcerpt(const char *s) noexcept {
while (*s) {
if (s[0] == ' ' && s[1] == '|' && (s[2] == ' ' || s[2] == '+')) {
return true;
}
if (!(s[0] == ' ' || s[0] == '+' || Is0To9(s[0]))) {
return false;
}
s++;
}
return true;
}
int RecogniseErrorListLine(const char *lineBuffer, Sci_PositionU lengthLine, Sci_Position &startValue) {
if (lineBuffer[0] == '>') {
// Command or return status
return SCE_ERR_CMD;
@ -106,7 +121,8 @@ static int RecogniseErrorListLine(const char *lineBuffer, Sci_PositionU lengthLi
// perl error message:
// <message> at <file> line <line>
return SCE_ERR_PERL;
} else if ((memcmp(lineBuffer, " at ", 6) == 0) &&
} else if ((lengthLine >= 6) &&
(memcmp(lineBuffer, " at ", 6) == 0) &&
strstr(lineBuffer, ":line ")) {
// A .NET traceback
return SCE_ERR_NET;
@ -131,6 +147,11 @@ static int RecogniseErrorListLine(const char *lineBuffer, Sci_PositionU lengthLi
// Microsoft linker warning:
// {<object> : } warning LNK9999
return SCE_ERR_MS;
} else if (IsGccExcerpt(lineBuffer)) {
// GCC code excerpt and pointer to issue
// 73 | GTimeVal last_popdown;
// | ^~~~~~~~~~~~
return SCE_ERR_GCC_EXCERPT;
} else {
// Look for one of the following formats:
// GCC: <filename>:<line>:<message>
@ -141,7 +162,7 @@ static int RecogniseErrorListLine(const char *lineBuffer, Sci_PositionU lengthLi
// CTags: <identifier>\t<filename>\t<message>
// Lua 5 traceback: \t<filename>:<line>:<message>
// Lua 5.1: <exe>: <filename>:<line>:<message>
bool initialTab = (lineBuffer[0] == '\t');
const bool initialTab = (lineBuffer[0] == '\t');
bool initialColonPart = false;
bool canBeCtags = !initialTab; // For ctags must have an identifier with no spaces then a tab
enum { stInitial,
@ -151,7 +172,7 @@ static int RecogniseErrorListLine(const char *lineBuffer, Sci_PositionU lengthLi
stUnrecognized
} state = stInitial;
for (Sci_PositionU i = 0; i < lengthLine; i++) {
char ch = lineBuffer[i];
const char ch = lineBuffer[i];
char chNext = ' ';
if ((i + 1) < lengthLine)
chNext = lineBuffer[i + 1];
@ -176,7 +197,7 @@ static int RecogniseErrorListLine(const char *lineBuffer, Sci_PositionU lengthLi
canBeCtags = false;
}
} else if (state == stGccStart) { // <filename>:
state = Is0To9(ch) ? stGccDigit : stUnrecognized;
state = ((ch == '-') || Is0To9(ch)) ? stGccDigit : stUnrecognized;
} else if (state == stGccDigit) { // <filename>:<line>
if (ch == ':') {
state = stGccColumn; // :9.*: is GCC
@ -207,14 +228,13 @@ static int RecogniseErrorListLine(const char *lineBuffer, Sci_PositionU lengthLi
} else if ((ch == ':' && chNext == ' ') || (ch == ' ')) {
// Possibly Delphi.. don't test against chNext as it's one of the strings below.
char word[512];
Sci_PositionU j, chPos;
unsigned numstep;
chPos = 0;
if (ch == ' ')
numstep = 1; // ch was ' ', handle as if it's a delphi errorline, only add 1 to i.
else
numstep = 2; // otherwise add 2.
for (j = i + numstep; j < lengthLine && IsAlphabetic(lineBuffer[j]) && chPos < sizeof(word) - 1; j++)
Sci_PositionU chPos = 0;
for (Sci_PositionU j = i + numstep; j < lengthLine && IsAlphabetic(lineBuffer[j]) && chPos < sizeof(word) - 1; j++)
word[chPos++] = lineBuffer[j];
word[chPos] = 0;
if (!CompareCaseInsensitive(word, "error") || !CompareCaseInsensitive(word, "warning") ||
@ -269,13 +289,11 @@ static int RecogniseErrorListLine(const char *lineBuffer, Sci_PositionU lengthLi
#define CSI "\033["
namespace {
bool SequenceEnd(int ch) {
constexpr bool SequenceEnd(int ch) noexcept {
return (ch == 0) || ((ch >= '@') && (ch <= '~'));
}
int StyleFromSequence(const char *seq) {
int StyleFromSequence(const char *seq) noexcept {
int bold = 0;
int colour = 0;
while (!SequenceEnd(*seq)) {
@ -302,21 +320,19 @@ int StyleFromSequence(const char *seq) {
return SCE_ERR_ES_BLACK + bold * 8 + colour;
}
}
static void ColouriseErrorListLine(
char *lineBuffer,
Sci_PositionU lengthLine,
void ColouriseErrorListLine(
const std::string &lineBuffer,
Sci_PositionU endPos,
Accessor &styler,
bool valueSeparate,
bool escapeSequences) {
Sci_Position startValue = -1;
int style = RecogniseErrorListLine(lineBuffer, lengthLine, startValue);
if (escapeSequences && strstr(lineBuffer, CSI)) {
const int startPos = endPos - lengthLine;
const char *linePortion = lineBuffer;
int startPortion = startPos;
const Sci_PositionU lengthLine = lineBuffer.length();
const int style = RecogniseErrorListLine(lineBuffer.c_str(), lengthLine, startValue);
if (escapeSequences && strstr(lineBuffer.c_str(), CSI)) {
const Sci_Position startPos = endPos - lengthLine;
const char *linePortion = lineBuffer.c_str();
Sci_Position startPortion = startPos;
int portionStyle = style;
while (const char *startSeq = strstr(linePortion, CSI)) {
if (startSeq > linePortion) {
@ -325,7 +341,7 @@ static void ColouriseErrorListLine(
const char *endSeq = startSeq + 2;
while (!SequenceEnd(*endSeq))
endSeq++;
const int endSeqPosition = startPortion + static_cast<int>(endSeq - linePortion) + 1;
const Sci_Position endSeqPosition = startPortion + static_cast<Sci_Position>(endSeq - linePortion) + 1;
switch (*endSeq) {
case 0:
styler.ColourTo(endPos, SCE_ERR_ESCSEQ_UNKNOWN);
@ -355,40 +371,39 @@ static void ColouriseErrorListLine(
}
}
static void ColouriseErrorListDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) {
char lineBuffer[10000];
void ColouriseErrorListDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) {
std::string lineBuffer;
styler.StartAt(startPos);
styler.StartSegment(startPos);
Sci_PositionU linePos = 0;
// property lexer.errorlist.value.separate
// For lines in the output pane that are matches from Find in Files or GCC-style
// diagnostics, style the path and line number separately from the rest of the
// line with style 21 used for the rest of the line.
// This allows matched text to be more easily distinguished from its location.
bool valueSeparate = styler.GetPropertyInt("lexer.errorlist.value.separate", 0) != 0;
const bool valueSeparate = styler.GetPropertyInt("lexer.errorlist.value.separate", 0) != 0;
// property lexer.errorlist.escape.sequences
// Set to 1 to interpret escape sequences.
const bool escapeSequences = styler.GetPropertyInt("lexer.errorlist.escape.sequences") != 0;
for (Sci_PositionU i = startPos; i < startPos + length; i++) {
lineBuffer[linePos++] = styler[i];
if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
// End of line (or of line buffer) met, colourise it
lineBuffer[linePos] = '\0';
ColouriseErrorListLine(lineBuffer, linePos, i, styler, valueSeparate, escapeSequences);
linePos = 0;
lineBuffer.push_back(styler[i]);
if (AtEOL(styler, i)) {
// End of line met, colourise it
ColouriseErrorListLine(lineBuffer, i, styler, valueSeparate, escapeSequences);
lineBuffer.clear();
}
}
if (linePos > 0) { // Last line does not have ending characters
lineBuffer[linePos] = '\0';
ColouriseErrorListLine(lineBuffer, linePos, startPos + length - 1, styler, valueSeparate, escapeSequences);
if (!lineBuffer.empty()) { // Last line does not have ending characters
ColouriseErrorListLine(lineBuffer, startPos + length - 1, styler, valueSeparate, escapeSequences);
}
}
static const char *const emptyWordListDesc[] = {
0
const char *const emptyWordListDesc[] = {
nullptr
};
}
LexerModule lmErrorList(SCLEX_ERRORLIST, ColouriseErrorListDoc, "errorlist", 0, emptyWordListDesc);

View file

@ -1,5 +1,5 @@
// Scintilla source code edit control
/** @file LexFlagShip.cxx
/** @file LexFlagship.cxx
** Lexer for Harbour and FlagShip.
** (Syntactically compatible to other xBase dialects, like Clipper, dBase, Clip, FoxPro etc.)
**/
@ -26,9 +26,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
// Extended to accept accented characters
static inline bool IsAWordChar(int ch)

View file

@ -23,9 +23,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsAWordStart(int ch) {
return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.');

View file

@ -25,9 +25,7 @@
#include "LexerModule.h"
/***************************************/
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
/***********************************************/
static inline bool IsAWordChar(const int ch) {
@ -120,14 +118,6 @@ static void ColouriseFortranDoc(Sci_PositionU startPos, Sci_Position length, int
continue;
}
/***************************************/
// Hanndle preprocessor directives
if (sc.ch == '#' && numNonBlank == 1)
{
sc.SetState(SCE_F_PREPROCESSOR);
while (!sc.atLineEnd && sc.More())
sc.Forward(); // Until line end
}
/***************************************/
// Handle line continuation generically.
if (!isFixFormat && sc.ch == '&' && sc.state != SCE_F_COMMENT) {
char chTemp = ' ';
@ -143,7 +133,11 @@ static void ColouriseFortranDoc(Sci_PositionU startPos, Sci_Position length, int
int currentState = sc.state;
sc.SetState(SCE_F_CONTINUATION);
sc.ForwardSetState(SCE_F_DEFAULT);
while (IsASpace(sc.ch) && sc.More()) sc.Forward();
while (IsASpace(sc.ch) && sc.More()) {
sc.Forward();
if (sc.atLineStart) numNonBlank = 0;
if (!IsASpaceOrTab(sc.ch)) numNonBlank ++;
}
if (sc.ch == '&') {
sc.SetState(SCE_F_CONTINUATION);
sc.Forward();
@ -152,6 +146,14 @@ static void ColouriseFortranDoc(Sci_PositionU startPos, Sci_Position length, int
}
}
/***************************************/
// Hanndle preprocessor directives
if (sc.ch == '#' && numNonBlank == 1)
{
sc.SetState(SCE_F_PREPROCESSOR);
while (!sc.atLineEnd && sc.More())
sc.Forward(); // Until line end
}
/***************************************/
// Determine if the current state should terminate.
if (sc.state == SCE_F_OPERATOR) {
sc.SetState(SCE_F_DEFAULT);
@ -223,7 +225,7 @@ static void ColouriseFortranDoc(Sci_PositionU startPos, Sci_Position length, int
if (sc.state == SCE_F_DEFAULT) {
if (sc.ch == '!') {
if (sc.MatchIgnoreCase("!dec$") || sc.MatchIgnoreCase("!dir$") ||
sc.MatchIgnoreCase("!ms$") || sc.chNext == '$') {
sc.MatchIgnoreCase("!ms$") || sc.chNext == '$') {
sc.SetState(SCE_F_PREPROCESSOR);
} else {
sc.SetState(SCE_F_COMMENT);
@ -233,7 +235,7 @@ static void ColouriseFortranDoc(Sci_PositionU startPos, Sci_Position length, int
} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
sc.SetState(SCE_F_NUMBER);
} else if ((tolower(sc.ch) == 'b' || tolower(sc.ch) == 'o' ||
tolower(sc.ch) == 'z') && (sc.chNext == '\"' || sc.chNext == '\'')) {
tolower(sc.ch) == 'z') && (sc.chNext == '\"' || sc.chNext == '\'')) {
sc.SetState(SCE_F_NUMBER);
sc.Forward();
} else if (sc.ch == '.' && isalpha(sc.chNext)) {
@ -252,6 +254,165 @@ static void ColouriseFortranDoc(Sci_PositionU startPos, Sci_Position length, int
sc.Complete();
}
/***************************************/
static void CheckLevelCommentLine(const unsigned int nComL,
Sci_Position nComColB[], Sci_Position nComColF[], Sci_Position &nComCur,
bool comLineB[], bool comLineF[], bool &comLineCur,
int &levelDeltaNext) {
levelDeltaNext = 0;
if (!comLineCur) {
return;
}
if (!comLineF[0] || nComColF[0] != nComCur) {
unsigned int i=0;
for (; i<nComL; i++) {
if (!comLineB[i] || nComColB[i] != nComCur) {
break;
}
}
if (i == nComL) {
levelDeltaNext = -1;
}
}
else if (!comLineB[0] || nComColB[0] != nComCur) {
unsigned int i=0;
for (; i<nComL; i++) {
if (!comLineF[i] || nComColF[i] != nComCur) {
break;
}
}
if (i == nComL) {
levelDeltaNext = 1;
}
}
}
/***************************************/
static void GetIfLineComment(Accessor &styler, bool isFixFormat, const Sci_Position line, bool &isComLine, Sci_Position &comCol) {
Sci_Position col = 0;
isComLine = false;
Sci_Position pos = styler.LineStart(line);
Sci_Position len = styler.Length();
while(pos<len) {
char ch = styler.SafeGetCharAt(pos);
if (ch == '!' || (isFixFormat && col == 0 && (tolower(ch) == 'c' || ch == '*'))) {
isComLine = true;
comCol = col;
break;
}
else if (!IsABlank(ch) || IsALineEnd(ch)) {
break;
}
pos++;
col++;
}
}
/***************************************/
static void StepCommentLine(Accessor &styler, bool isFixFormat, Sci_Position lineCurrent, const unsigned int nComL,
Sci_Position nComColB[], Sci_Position nComColF[], Sci_Position &nComCur,
bool comLineB[], bool comLineF[], bool &comLineCur) {
Sci_Position nLineTotal = styler.GetLine(styler.Length()-1) + 1;
if (lineCurrent >= nLineTotal) {
return;
}
for (int i=nComL-2; i>=0; i--) {
nComColB[i+1] = nComColB[i];
comLineB[i+1] = comLineB[i];
}
nComColB[0] = nComCur;
comLineB[0] = comLineCur;
nComCur = nComColF[0];
comLineCur = comLineF[0];
for (unsigned int i=0; i+1<nComL; i++) {
nComColF[i] = nComColF[i+1];
comLineF[i] = comLineF[i+1];
}
Sci_Position chL = lineCurrent + nComL;
if (chL < nLineTotal) {
GetIfLineComment(styler, isFixFormat, chL, comLineF[nComL-1], nComColF[nComL-1]);
}
else {
comLineF[nComL-1] = false;
}
}
/***************************************/
static void CheckBackComLines(Accessor &styler, bool isFixFormat, Sci_Position lineCurrent, const unsigned int nComL,
Sci_Position nComColB[], Sci_Position nComColF[], Sci_Position nComCur,
bool comLineB[], bool comLineF[], bool &comLineCur) {
unsigned int nLines = nComL + nComL + 1;
bool* comL = new bool[nLines];
Sci_Position* nComCol = new Sci_Position[nLines];
bool comL0;
Sci_Position nComCol0;
GetIfLineComment(styler, isFixFormat, lineCurrent-nComL-1, comL0, nComCol0);
for (unsigned int i=0; i<nComL; i++) {
unsigned copyTo = nComL - i - 1;
comL[copyTo] = comLineB[i];
nComCol[copyTo] = nComColB[i];
}
assert(nComL < nLines);
comL[nComL] = comLineCur;
nComCol[nComL] = nComCur;
for (unsigned int i=0; i<nComL; i++) {
unsigned copyTo = i + nComL + 1;
comL[copyTo] = comLineF[i];
nComCol[copyTo] = nComColF[i];
}
Sci_Position lineC = lineCurrent - nComL + 1;
Sci_PositionU iStart;
if (lineC <= 0) {
lineC = 0;
iStart = nComL - lineCurrent;
}
else {
iStart = 1;
}
bool levChanged = false;
int lev = styler.LevelAt(lineC) & SC_FOLDLEVELNUMBERMASK;
for (Sci_PositionU i=iStart; i<=nComL; i++) {
if (comL[i] && (!comL[i-1] || nComCol[i] != nComCol[i-1])) {
bool increase = true;
Sci_PositionU until = i + nComL;
for (Sci_PositionU j=i+1; j<=until; j++) {
if (!comL[j] || nComCol[j] != nComCol[i]) {
increase = false;
break;
}
}
lev = styler.LevelAt(lineC) & SC_FOLDLEVELNUMBERMASK;
if (increase) {
int levH = lev | SC_FOLDLEVELHEADERFLAG;
lev += 1;
if (levH != styler.LevelAt(lineC)) {
styler.SetLevel(lineC, levH);
}
for (Sci_Position j=lineC+1; j<=lineCurrent; j++) {
if (lev != styler.LevelAt(j)) {
styler.SetLevel(j, lev);
}
}
break;
}
else {
if (lev != styler.LevelAt(lineC)) {
styler.SetLevel(lineC, lev);
}
}
levChanged = true;
}
else if (levChanged && comL[i]) {
if (lev != styler.LevelAt(lineC)) {
styler.SetLevel(lineC, lev);
}
}
lineC++;
}
delete[] comL;
delete[] nComCol;
}
/***************************************/
// To determine the folding level depending on keywords
static int classifyFoldPointFortran(const char* s, const char* prevWord, const char chNextNonBlank) {
int lev = 0;
@ -282,7 +443,7 @@ static int classifyFoldPointFortran(const char* s, const char* prevWord, const c
|| strcmp(s, "endsubroutine") == 0 || strcmp(s, "endtype") == 0
|| strcmp(s, "endwhere") == 0 || strcmp(s, "endcritical") == 0
|| (strcmp(prevWord, "module") == 0 && strcmp(s, "procedure") == 0) // Take care of the "module procedure" statement
|| strcmp(s, "endsubmodule") == 0) {
|| strcmp(s, "endsubmodule") == 0 || strcmp(s, "endteam") == 0) {
lev = -1;
} else if (strcmp(prevWord, "end") == 0 && strcmp(s, "if") == 0){ // end if
lev = 0;
@ -291,6 +452,8 @@ static int classifyFoldPointFortran(const char* s, const char* prevWord, const c
} else if ((strcmp(prevWord, "end") == 0 && strcmp(s, "procedure") == 0)
|| strcmp(s, "endprocedure") == 0) {
lev = 1; // level back to 0, because no folding support for "module procedure" in submodule
} else if (strcmp(prevWord, "change") == 0 && strcmp(s, "team") == 0){ // change team
lev = 1;
}
return lev;
}
@ -298,29 +461,62 @@ static int classifyFoldPointFortran(const char* s, const char* prevWord, const c
// Folding the code
static void FoldFortranDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
Accessor &styler, bool isFixFormat) {
//
// bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
// Do not know how to fold the comment at the moment.
//
bool foldComment = styler.GetPropertyInt("fold.comment", 1) != 0;
bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
Sci_PositionU endPos = startPos + length;
int visibleChars = 0;
Sci_Position lineCurrent = styler.GetLine(startPos);
int levelCurrent;
bool isPrevLine;
if (lineCurrent > 0) {
lineCurrent--;
startPos = styler.LineStart(lineCurrent);
levelCurrent = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
isPrevLine = true;
} else {
levelCurrent = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
isPrevLine = false;
}
char chNext = styler[startPos];
int styleNext = styler.StyleAt(startPos);
int style = initStyle;
int levelDeltaNext = 0;
const unsigned int nComL = 3; // defines how many comment lines should be before they are folded
Sci_Position nComColB[nComL] = {};
Sci_Position nComColF[nComL] = {};
Sci_Position nComCur = 0;
bool comLineB[nComL] = {};
bool comLineF[nComL] = {};
bool comLineCur;
Sci_Position nLineTotal = styler.GetLine(styler.Length()-1) + 1;
if (foldComment) {
for (unsigned int i=0; i<nComL; i++) {
Sci_Position chL = lineCurrent-(i+1);
if (chL < 0) {
comLineB[i] = false;
break;
}
GetIfLineComment(styler, isFixFormat, chL, comLineB[i], nComColB[i]);
if (!comLineB[i]) {
for (unsigned int j=i+1; j<nComL; j++) {
comLineB[j] = false;
}
break;
}
}
for (unsigned int i=0; i<nComL; i++) {
Sci_Position chL = lineCurrent+i+1;
if (chL >= nLineTotal) {
comLineF[i] = false;
break;
}
GetIfLineComment(styler, isFixFormat, chL, comLineF[i], nComColF[i]);
}
GetIfLineComment(styler, isFixFormat, lineCurrent, comLineCur, nComCur);
CheckBackComLines(styler, isFixFormat, lineCurrent, nComL, nComColB, nComColF, nComCur,
comLineB, comLineF, comLineCur);
}
int levelCurrent = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
/***************************************/
Sci_Position lastStart = 0;
char prevWord[32] = "";
@ -463,6 +659,11 @@ static void FoldFortranDoc(Sci_PositionU startPos, Sci_Position length, int init
}
}
if (atEOL) {
if (foldComment) {
int ldNext;
CheckLevelCommentLine(nComL, nComColB, nComColF, nComCur, comLineB, comLineF, comLineCur, ldNext);
levelDeltaNext += ldNext;
}
int lev = levelCurrent;
if (visibleChars == 0 && foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG;
@ -477,6 +678,11 @@ static void FoldFortranDoc(Sci_PositionU startPos, Sci_Position length, int init
visibleChars = 0;
strcpy(prevWord, "");
isPrevLine = false;
if (foldComment) {
StepCommentLine(styler, isFixFormat, lineCurrent, nComL, nComColB, nComColF, nComCur,
comLineB, comLineF, comLineCur);
}
}
/***************************************/
if (!isspacechar(ch)) visibleChars++;

View file

@ -24,9 +24,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsGAPOperator(char ch) {
if (IsASCII(ch) && isalnum(ch)) return false;

View file

@ -1,5 +1,6 @@
// Scintilla source code edit control
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// @file LexGui4Cli.cxx
/*
This is the Lexer for Gui4Cli, included in SciLexer.dll
- by d. Keletsekis, 2/10/2003
@ -39,9 +40,7 @@ val SCE_GC_OPERATOR=9
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
#define debug Platform::DebugPrintf
@ -68,7 +67,7 @@ inline bool isGCOperator(int ch)
#define isFoldPoint(x) ((styler.LevelAt(x) & SC_FOLDLEVELNUMBERMASK) == 1024)
static void colorFirstWord(WordList *keywordlists[], Accessor &styler,
StyleContext *sc, char *buff, Sci_Position length, int)
StyleContext *sc, char *buff, Sci_Position length, Sci_Position)
{
Sci_Position c = 0;
while (sc->More() && isSpaceOrNL(sc->ch))

File diff suppressed because it is too large Load diff

View file

@ -26,6 +26,7 @@
#include <ctype.h>
#include <string>
#include <vector>
#include <map>
#include "ILexer.h"
@ -41,10 +42,9 @@
#include "CharacterCategory.h"
#include "LexerModule.h"
#include "OptionSet.h"
#include "DefaultLexer.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
// See https://github.com/ghc/ghc/blob/master/compiler/parser/Lexer.x#L1682
// Note, letter modifiers are prohibited.
@ -269,7 +269,7 @@ struct OptionSetHaskell : public OptionSet<OptionsHaskell> {
}
};
class LexerHaskell : public ILexer {
class LexerHaskell : public DefaultLexer {
bool literate;
Sci_Position firstImportLine;
int firstImportIndent;
@ -390,45 +390,50 @@ class LexerHaskell : public ILexer {
public:
LexerHaskell(bool literate_)
: literate(literate_)
: DefaultLexer(literate_ ? "literatehaskell" : "haskell", literate_ ? SCLEX_LITERATEHASKELL : SCLEX_HASKELL)
, literate(literate_)
, firstImportLine(-1)
, firstImportIndent(0)
{}
virtual ~LexerHaskell() {}
void SCI_METHOD Release() {
void SCI_METHOD Release() override {
delete this;
}
int SCI_METHOD Version() const {
return lvOriginal;
int SCI_METHOD Version() const override {
return lvIdentity;
}
const char * SCI_METHOD PropertyNames() {
const char * SCI_METHOD PropertyNames() override {
return osHaskell.PropertyNames();
}
int SCI_METHOD PropertyType(const char *name) {
int SCI_METHOD PropertyType(const char *name) override {
return osHaskell.PropertyType(name);
}
const char * SCI_METHOD DescribeProperty(const char *name) {
const char * SCI_METHOD DescribeProperty(const char *name) override {
return osHaskell.DescribeProperty(name);
}
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val);
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
const char * SCI_METHOD DescribeWordListSets() {
const char * SCI_METHOD PropertyGet(const char *key) override {
return osHaskell.PropertyGet(key);
}
const char * SCI_METHOD DescribeWordListSets() override {
return osHaskell.DescribeWordListSets();
}
Sci_Position SCI_METHOD WordListSet(int n, const char *wl);
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);
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);
void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override;
void * SCI_METHOD PrivateCall(int, void *) {
void * SCI_METHOD PrivateCall(int, void *) override {
return 0;
}

View file

@ -118,9 +118,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
// prototypes for general helper functions
static inline bool IsNewline(const int ch);
@ -651,7 +649,9 @@ static void ColouriseSrecDoc(Sci_PositionU startPos, Sci_Position length, int in
while (sc.More()) {
Sci_PositionU recStartPos;
int byteCount, reqByteCount, addrFieldSize, addrFieldType, dataFieldSize, dataFieldType;
Sci_Position reqByteCount;
Sci_Position dataFieldSize;
int byteCount, addrFieldSize, addrFieldType, dataFieldType;
int cs1, cs2;
switch (sc.state) {

View file

@ -0,0 +1,516 @@
// Scintilla source code edit control
/** @file LexHollywood.cxx
** Lexer for Hollywood
** Written by Andreas Falkenhahn, based on the BlitzBasic/PureBasic/Lua lexers
** Thanks to Nicholai Benalal
** For more information on Hollywood, see http://www.hollywood-mal.com/
** Mail me (andreas <at> airsoftsoftwair <dot> de) for any bugs.
** This code is subject to the same license terms as the rest of the Scintilla project:
** The License.txt file describes the conditions under which this software may be distributed.
**/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
#include <string>
#include <map>
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"
#include "DefaultLexer.h"
using namespace Scintilla;
/* Bits:
* 1 - whitespace
* 2 - operator
* 4 - identifier
* 8 - decimal digit
* 16 - hex digit
* 32 - bin digit
* 64 - letter
*/
static int character_classification[128] =
{
0, // NUL ($0)
0, // SOH ($1)
0, // STX ($2)
0, // ETX ($3)
0, // EOT ($4)
0, // ENQ ($5)
0, // ACK ($6)
0, // BEL ($7)
0, // BS ($8)
1, // HT ($9)
1, // LF ($A)
0, // VT ($B)
0, // FF ($C)
1, // CR ($D)
0, // SO ($E)
0, // SI ($F)
0, // DLE ($10)
0, // DC1 ($11)
0, // DC2 ($12)
0, // DC3 ($13)
0, // DC4 ($14)
0, // NAK ($15)
0, // SYN ($16)
0, // ETB ($17)
0, // CAN ($18)
0, // EM ($19)
0, // SUB ($1A)
0, // ESC ($1B)
0, // FS ($1C)
0, // GS ($1D)
0, // RS ($1E)
0, // US ($1F)
1, // space ($20)
4, // ! ($21)
0, // " ($22)
0, // # ($23)
4, // $ ($24)
2, // % ($25)
2, // & ($26)
2, // ' ($27)
2, // ( ($28)
2, // ) ($29)
2, // * ($2A)
2, // + ($2B)
2, // , ($2C)
2, // - ($2D)
// NB: we treat "." as an identifier although it is also an operator and a decimal digit
// the reason why we treat it as an identifier is to support syntax highlighting for
// plugin commands which always use a "." in their names, e.g. pdf.OpenDocument();
// we handle the decimal digit case manually below so that 3.1415 and .123 is styled correctly
// the collateral damage of treating "." as an identifier is that "." is never styled
// SCE_HOLLYWOOD_OPERATOR
4, // . ($2E)
2, // / ($2F)
28, // 0 ($30)
28, // 1 ($31)
28, // 2 ($32)
28, // 3 ($33)
28, // 4 ($34)
28, // 5 ($35)
28, // 6 ($36)
28, // 7 ($37)
28, // 8 ($38)
28, // 9 ($39)
2, // : ($3A)
2, // ; ($3B)
2, // < ($3C)
2, // = ($3D)
2, // > ($3E)
2, // ? ($3F)
0, // @ ($40)
84, // A ($41)
84, // B ($42)
84, // C ($43)
84, // D ($44)
84, // E ($45)
84, // F ($46)
68, // G ($47)
68, // H ($48)
68, // I ($49)
68, // J ($4A)
68, // K ($4B)
68, // L ($4C)
68, // M ($4D)
68, // N ($4E)
68, // O ($4F)
68, // P ($50)
68, // Q ($51)
68, // R ($52)
68, // S ($53)
68, // T ($54)
68, // U ($55)
68, // V ($56)
68, // W ($57)
68, // X ($58)
68, // Y ($59)
68, // Z ($5A)
2, // [ ($5B)
2, // \ ($5C)
2, // ] ($5D)
2, // ^ ($5E)
68, // _ ($5F)
2, // ` ($60)
84, // a ($61)
84, // b ($62)
84, // c ($63)
84, // d ($64)
84, // e ($65)
84, // f ($66)
68, // g ($67)
68, // h ($68)
68, // i ($69)
68, // j ($6A)
68, // k ($6B)
68, // l ($6C)
68, // m ($6D)
68, // n ($6E)
68, // o ($6F)
68, // p ($70)
68, // q ($71)
68, // r ($72)
68, // s ($73)
68, // t ($74)
68, // u ($75)
68, // v ($76)
68, // w ($77)
68, // x ($78)
68, // y ($79)
68, // z ($7A)
2, // { ($7B)
2, // | ($7C)
2, // } ($7D)
2, // ~ ($7E)
0, // &#127; ($7F)
};
static bool IsSpace(int c) {
return c < 128 && (character_classification[c] & 1);
}
static bool IsOperator(int c) {
return c < 128 && (character_classification[c] & 2);
}
static bool IsIdentifier(int c) {
return c < 128 && (character_classification[c] & 4);
}
static bool IsDigit(int c) {
return c < 128 && (character_classification[c] & 8);
}
static bool IsHexDigit(int c) {
return c < 128 && (character_classification[c] & 16);
}
static int LowerCase(int c)
{
if (c >= 'A' && c <= 'Z')
return 'a' + c - 'A';
return c;
}
static int CheckHollywoodFoldPoint(char const *token) {
if (!strcmp(token, "function")) {
return 1;
}
if (!strcmp(token, "endfunction")) {
return -1;
}
return 0;
}
// An individual named option for use in an OptionSet
// Options used for LexerHollywood
struct OptionsHollywood {
bool fold;
bool foldCompact;
OptionsHollywood() {
fold = false;
foldCompact = false;
}
};
static const char * const hollywoodWordListDesc[] = {
"Hollywood keywords",
"Hollywood standard API functions",
"Hollywood plugin API functions",
"Hollywood plugin methods",
0
};
struct OptionSetHollywood : public OptionSet<OptionsHollywood> {
OptionSetHollywood(const char * const wordListDescriptions[]) {
DefineProperty("fold", &OptionsHollywood::fold);
DefineProperty("fold.compact", &OptionsHollywood::foldCompact);
DefineWordListSets(wordListDescriptions);
}
};
class LexerHollywood : public DefaultLexer {
int (*CheckFoldPoint)(char const *);
WordList keywordlists[4];
OptionsHollywood options;
OptionSetHollywood osHollywood;
public:
LexerHollywood(int (*CheckFoldPoint_)(char const *), const char * const wordListDescriptions[]) :
DefaultLexer("hollywood", SCLEX_HOLLYWOOD),
CheckFoldPoint(CheckFoldPoint_),
osHollywood(wordListDescriptions) {
}
virtual ~LexerHollywood() {
}
void SCI_METHOD Release() override {
delete this;
}
int SCI_METHOD Version() const override {
return lvIdentity;
}
const char * SCI_METHOD PropertyNames() override {
return osHollywood.PropertyNames();
}
int SCI_METHOD PropertyType(const char *name) override {
return osHollywood.PropertyType(name);
}
const char * SCI_METHOD DescribeProperty(const char *name) override {
return osHollywood.DescribeProperty(name);
}
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
const char * SCI_METHOD PropertyGet(const char* key) override {
return osHollywood.PropertyGet(key);
}
const char * SCI_METHOD DescribeWordListSets() override {
return osHollywood.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 0;
}
static ILexer *LexerFactoryHollywood() {
return new LexerHollywood(CheckHollywoodFoldPoint, hollywoodWordListDesc);
}
};
Sci_Position SCI_METHOD LexerHollywood::PropertySet(const char *key, const char *val) {
if (osHollywood.PropertySet(&options, key, val)) {
return 0;
}
return -1;
}
Sci_Position SCI_METHOD LexerHollywood::WordListSet(int n, const char *wl) {
WordList *wordListN = 0;
switch (n) {
case 0:
wordListN = &keywordlists[0];
break;
case 1:
wordListN = &keywordlists[1];
break;
case 2:
wordListN = &keywordlists[2];
break;
case 3:
wordListN = &keywordlists[3];
break;
}
Sci_Position firstModification = -1;
if (wordListN) {
WordList wlNew;
wlNew.Set(wl);
if (*wordListN != wlNew) {
wordListN->Set(wl);
firstModification = 0;
}
}
return firstModification;
}
void SCI_METHOD LexerHollywood::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) {
LexAccessor styler(pAccess);
styler.StartAt(startPos);
bool inString = false;
StyleContext sc(startPos, length, initStyle, styler);
// Can't use sc.More() here else we miss the last character
for (; ; sc.Forward())
{
if (sc.atLineStart) inString = false;
if (sc.ch == '\"' && sc.chPrev != '\\') inString = !inString;
if (sc.state == SCE_HOLLYWOOD_IDENTIFIER) {
if (!IsIdentifier(sc.ch)) {
char s[100];
int kstates[4] = {
SCE_HOLLYWOOD_KEYWORD,
SCE_HOLLYWOOD_STDAPI,
SCE_HOLLYWOOD_PLUGINAPI,
SCE_HOLLYWOOD_PLUGINMETHOD,
};
sc.GetCurrentLowered(s, sizeof(s));
for (int i = 0; i < 4; i++) {
if (keywordlists[i].InList(s)) {
sc.ChangeState(kstates[i]);
}
}
sc.SetState(SCE_HOLLYWOOD_DEFAULT);
}
} else if (sc.state == SCE_HOLLYWOOD_OPERATOR) {
// always reset to default on operators because otherwise
// comments won't be recognized in sequences like "+/* Hello*/"
// --> "+/*" would be recognized as a sequence of operators
// if (!IsOperator(sc.ch)) sc.SetState(SCE_HOLLYWOOD_DEFAULT);
sc.SetState(SCE_HOLLYWOOD_DEFAULT);
} else if (sc.state == SCE_HOLLYWOOD_PREPROCESSOR) {
if (!IsIdentifier(sc.ch))
sc.SetState(SCE_HOLLYWOOD_DEFAULT);
} else if (sc.state == SCE_HOLLYWOOD_CONSTANT) {
if (!IsIdentifier(sc.ch))
sc.SetState(SCE_HOLLYWOOD_DEFAULT);
} else if (sc.state == SCE_HOLLYWOOD_NUMBER) {
if (!IsDigit(sc.ch) && sc.ch != '.')
sc.SetState(SCE_HOLLYWOOD_DEFAULT);
} else if (sc.state == SCE_HOLLYWOOD_HEXNUMBER) {
if (!IsHexDigit(sc.ch))
sc.SetState(SCE_HOLLYWOOD_DEFAULT);
} else if (sc.state == SCE_HOLLYWOOD_STRING) {
if (sc.ch == '"') {
sc.ForwardSetState(SCE_HOLLYWOOD_DEFAULT);
}
if (sc.atLineEnd) {
sc.SetState(SCE_HOLLYWOOD_DEFAULT);
}
} else if (sc.state == SCE_HOLLYWOOD_COMMENT) {
if (sc.atLineEnd) {
sc.SetState(SCE_HOLLYWOOD_DEFAULT);
}
} else if (sc.state == SCE_HOLLYWOOD_COMMENTBLOCK) {
if (sc.Match("*/") && !inString) {
sc.Forward();
sc.ForwardSetState(SCE_HOLLYWOOD_DEFAULT);
}
} else if (sc.state == SCE_HOLLYWOOD_STRINGBLOCK) {
if (sc.Match("]]") && !inString) {
sc.Forward();
sc.ForwardSetState(SCE_HOLLYWOOD_DEFAULT);
}
}
if (sc.state == SCE_HOLLYWOOD_DEFAULT) {
if (sc.Match(';')) {
sc.SetState(SCE_HOLLYWOOD_COMMENT);
} else if (sc.Match("/*")) {
sc.SetState(SCE_HOLLYWOOD_COMMENTBLOCK);
sc.Forward();
} else if (sc.Match("[[")) {
sc.SetState(SCE_HOLLYWOOD_STRINGBLOCK);
sc.Forward();
} else if (sc.Match('"')) {
sc.SetState(SCE_HOLLYWOOD_STRING);
} else if (sc.Match('$')) {
sc.SetState(SCE_HOLLYWOOD_HEXNUMBER);
} else if (sc.Match("0x") || sc.Match("0X")) { // must be before IsDigit() because of 0x
sc.SetState(SCE_HOLLYWOOD_HEXNUMBER);
sc.Forward();
} else if (sc.ch == '.' && (sc.chNext >= '0' && sc.chNext <= '9')) { // ".1234" style numbers
sc.SetState(SCE_HOLLYWOOD_NUMBER);
sc.Forward();
} else if (IsDigit(sc.ch)) {
sc.SetState(SCE_HOLLYWOOD_NUMBER);
} else if (sc.Match('#')) {
sc.SetState(SCE_HOLLYWOOD_CONSTANT);
} else if (sc.Match('@')) {
sc.SetState(SCE_HOLLYWOOD_PREPROCESSOR);
} else if (IsOperator(sc.ch)) {
sc.SetState(SCE_HOLLYWOOD_OPERATOR);
} else if (IsIdentifier(sc.ch)) {
sc.SetState(SCE_HOLLYWOOD_IDENTIFIER);
}
}
if (!sc.More())
break;
}
sc.Complete();
}
void SCI_METHOD LexerHollywood::Fold(Sci_PositionU startPos, Sci_Position length, int /* initStyle */, IDocument *pAccess) {
if (!options.fold)
return;
LexAccessor styler(pAccess);
Sci_PositionU lengthDoc = startPos + length;
int visibleChars = 0;
Sci_Position lineCurrent = styler.GetLine(startPos);
int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
int levelCurrent = levelPrev;
char chNext = styler[startPos];
int styleNext = styler.StyleAt(startPos);
int done = 0;
char word[256];
int wordlen = 0;
for (Sci_PositionU i = startPos; i < lengthDoc; i++) {
char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
int style = styleNext;
styleNext = styler.StyleAt(i + 1);
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
if (!done) {
if (wordlen) { // are we scanning a token already?
word[wordlen] = static_cast<char>(LowerCase(ch));
if (!IsIdentifier(ch)) { // done with token
word[wordlen] = '\0';
levelCurrent += CheckFoldPoint(word);
done = 1;
} else if (wordlen < 255) {
wordlen++;
}
} else { // start scanning at first non-whitespace character
if (!IsSpace(ch)) {
if (style != SCE_HOLLYWOOD_COMMENTBLOCK && IsIdentifier(ch)) {
word[0] = static_cast<char>(LowerCase(ch));
wordlen = 1;
} else // done with this line
done = 1;
}
}
}
if (atEOL) {
int lev = levelPrev;
if (visibleChars == 0 && options.foldCompact) {
lev |= SC_FOLDLEVELWHITEFLAG;
}
if ((levelCurrent > levelPrev) && (visibleChars > 0)) {
lev |= SC_FOLDLEVELHEADERFLAG;
}
if (lev != styler.LevelAt(lineCurrent)) {
styler.SetLevel(lineCurrent, lev);
}
lineCurrent++;
levelPrev = levelCurrent;
visibleChars = 0;
done = 0;
wordlen = 0;
}
if (!IsSpace(ch)) {
visibleChars++;
}
}
// Fill in the real level of the next line, keeping the current flags as they will be filled in later
int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}
LexerModule lmHollywood(SCLEX_HOLLYWOOD, LexerHollywood::LexerFactoryHollywood, "hollywood", hollywoodWordListDesc);

View file

@ -0,0 +1,71 @@
// Scintilla source code edit control
/** @file LexIndent.cxx
** Lexer for no language. Used for indentation-based folding of files.
**/
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
#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"
using namespace Scintilla;
static void ColouriseIndentDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[],
Accessor &styler) {
// Indent language means all style bytes are 0 so just mark the end - no need to fill in.
if (length > 0) {
styler.StartAt(startPos + length - 1);
styler.StartSegment(startPos + length - 1);
styler.ColourTo(startPos + length - 1, 0);
}
}
static void FoldIndentDoc(Sci_PositionU startPos, Sci_Position length, int /* initStyle */, WordList *[], Accessor &styler) {
int visibleCharsCurrent, visibleCharsNext;
int levelCurrent, levelNext;
Sci_PositionU i, lineEnd;
Sci_PositionU lengthDoc = startPos + length;
Sci_Position lineCurrent = styler.GetLine(startPos);
i = styler.LineStart(lineCurrent );
lineEnd = styler.LineStart(lineCurrent+1)-1;
if(lineEnd>=lengthDoc) lineEnd = lengthDoc-1;
while(styler[lineEnd]=='\n' || styler[lineEnd]=='\r') lineEnd--;
for(visibleCharsCurrent=0, levelCurrent=SC_FOLDLEVELBASE; !visibleCharsCurrent && i<=lineEnd; i++){
if(isspacechar(styler[i])) levelCurrent++;
else visibleCharsCurrent=1;
}
for(; i<lengthDoc; lineCurrent++) {
i = styler.LineStart(lineCurrent+1);
lineEnd = styler.LineStart(lineCurrent+2)-1;
if(lineEnd>=lengthDoc) lineEnd = lengthDoc-1;
while(styler[lineEnd]=='\n' || styler[lineEnd]=='\r') lineEnd--;
for(visibleCharsNext=0, levelNext=SC_FOLDLEVELBASE; !visibleCharsNext && i<=lineEnd; i++){
if(isspacechar(styler[i])) levelNext++;
else visibleCharsNext=1;
}
int lev = levelCurrent;
if(!visibleCharsCurrent) lev |= SC_FOLDLEVELWHITEFLAG;
else if(levelNext > levelCurrent) lev |= SC_FOLDLEVELHEADERFLAG;
styler.SetLevel(lineCurrent, lev);
levelCurrent = levelNext;
visibleCharsCurrent = visibleCharsNext;
}
}
LexerModule lmIndent(SCLEX_INDENT, ColouriseIndentDoc, "indent", FoldIndentDoc);

View file

@ -23,9 +23,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static void ColouriseInnoDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *keywordLists[], Accessor &styler) {
int state = SCE_INNO_DEFAULT;

View file

@ -27,10 +27,9 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"
#include "DefaultLexer.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static const char *const JSONWordListDesc[] = {
"JSON Keywords",
@ -128,7 +127,7 @@ struct OptionSetJSON : public OptionSet<OptionsJSON> {
}
};
class LexerJSON : public ILexer {
class LexerJSON : public DefaultLexer {
OptionsJSON options;
OptionSetJSON optSetJSON;
EscapeSequence escapeSeq;
@ -202,34 +201,38 @@ class LexerJSON : public ILexer {
public:
LexerJSON() :
DefaultLexer("json", SCLEX_JSON),
setOperators(CharacterSet::setNone, "[{}]:,"),
setURL(CharacterSet::setAlphaNum, "-._~:/?#[]@!$&'()*+,),="),
setKeywordJSONLD(CharacterSet::setAlpha, ":@"),
setKeywordJSON(CharacterSet::setAlpha, "$_") {
}
virtual ~LexerJSON() {}
virtual int SCI_METHOD Version() const {
return lvOriginal;
int SCI_METHOD Version() const override {
return lvIdentity;
}
virtual void SCI_METHOD Release() {
void SCI_METHOD Release() override {
delete this;
}
virtual const char *SCI_METHOD PropertyNames() {
const char *SCI_METHOD PropertyNames() override {
return optSetJSON.PropertyNames();
}
virtual int SCI_METHOD PropertyType(const char *name) {
int SCI_METHOD PropertyType(const char *name) override {
return optSetJSON.PropertyType(name);
}
virtual const char *SCI_METHOD DescribeProperty(const char *name) {
const char *SCI_METHOD DescribeProperty(const char *name) override {
return optSetJSON.DescribeProperty(name);
}
virtual Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) {
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override {
if (optSetJSON.PropertySet(&options, key, val)) {
return 0;
}
return -1;
}
virtual Sci_Position SCI_METHOD WordListSet(int n, const char *wl) {
const char * SCI_METHOD PropertyGet(const char *key) override {
return optSetJSON.PropertyGet(key);
}
Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override {
WordList *wordListN = 0;
switch (n) {
case 0:
@ -250,23 +253,23 @@ class LexerJSON : public ILexer {
}
return firstModification;
}
virtual void *SCI_METHOD PrivateCall(int, void *) {
void *SCI_METHOD PrivateCall(int, void *) override {
return 0;
}
static ILexer *LexerFactoryJSON() {
return new LexerJSON;
}
virtual const char *SCI_METHOD DescribeWordListSets() {
const char *SCI_METHOD DescribeWordListSets() override {
return optSetJSON.DescribeWordListSets();
}
virtual void SCI_METHOD Lex(Sci_PositionU startPos,
void SCI_METHOD Lex(Sci_PositionU startPos,
Sci_Position length,
int initStyle,
IDocument *pAccess);
virtual void SCI_METHOD Fold(Sci_PositionU startPos,
IDocument *pAccess) override;
void SCI_METHOD Fold(Sci_PositionU startPos,
Sci_Position length,
int initStyle,
IDocument *pAccess);
IDocument *pAccess) override;
};
void SCI_METHOD LexerJSON::Lex(Sci_PositionU startPos,

View file

@ -26,9 +26,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
/* KVIrc Script syntactic rules: http://www.kvirc.net/doc/doc_syntactic_rules.html */

View file

@ -24,9 +24,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
// Extended to accept accented characters
static inline bool IsAWordChar(int ch) {

View file

@ -0,0 +1,968 @@
/**
* Copyright 2006-2020 Mitchell mitchell.att.foicica.com. See License.txt.
*
* Lua-powered dynamic language lexer for Scintilla.
*
* For documentation on writing lexers, see *../doc/LPegLexer.html*.
*/
#if LPEG_LEXER
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <assert.h>
#include <ctype.h>
#if CURSES
#include <curses.h>
#endif
#include <set>
#include <sstream>
#include <vector>
#if !_WIN32
#include <dirent.h>
#else
#include <io.h>
#endif
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
#include "PropSetSimple.h"
#include "LexAccessor.h"
#include "LexerModule.h"
#include "DefaultLexer.h"
extern "C" {
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
LUALIB_API int luaopen_lpeg(lua_State *L);
}
using namespace Scintilla;
#ifndef NDEBUG
#define RECORD_STACK_TOP(l) int orig_stack_top = lua_gettop(l)
#define ASSERT_STACK_TOP(l) assert(lua_gettop(l) == orig_stack_top)
#else
#define RECORD_STACK_TOP(_) (void)0
#define ASSERT_STACK_TOP(_) (void)0
#endif
#if LUA_VERSION_NUM < 502
#define luaL_traceback(_,__,___,____) (void)0
#define luaL_requiref(l, s, f, _) \
(lua_pushcfunction(l, f), lua_pushstring(l, s), lua_call(l, 1, 1))
#define lua_rawlen lua_objlen
#define LUA_OK 0
#define lua_rawgetp(l, i, p) \
(lua_pushlightuserdata(l, p), lua_rawget(l, i), lua_type(l, -1))
#define lua_rawsetp(l, i, p) \
(lua_pushlightuserdata(l, p), lua_insert(l, -2), lua_rawset(l, i))
#endif
#if LUA_VERSION_NUM < 503
#define lua_getfield(l, i, k) (lua_getfield(l, i, k), lua_type(l, -1))
#define lua_rawget(l, i) (lua_rawget(l, i), lua_type(l, -1))
#endif
/** The LPeg Scintilla lexer. */
class LexerLPeg : public DefaultLexer {
// Lexer property keys.
const char * const LexerErrorKey = "lexer.lpeg.error";
const char * const LexerHomeKey = "lexer.lpeg.home";
const char * const LexerNameKey = "lexer.lpeg.name";
const char * const LexerThemeKey = "lexer.lpeg.color.theme";
/**
* The lexer's Lua state.
* It is cleared each time the lexer language changes unless `ownLua` is
* `true`.
*/
lua_State *L;
/**
* The flag indicating whether or not the Lua State is owned by the lexer.
*/
bool ownLua = true;
/**
* The set of properties for the lexer.
* The LexerHomeKey and LexerNameKey properties must be defined before running
* the lexer.
*/
PropSetSimple props;
/** The function to send Scintilla messages with. */
SciFnDirect SS = nullptr;
/** The Scintilla object the lexer belongs to. */
sptr_t sci = 0;
/**
* The flag indicating whether or not the lexer needs to be re-initialized.
* Re-initialization is required after the lexer language changes.
*/
bool reinit = true;
/**
* The flag indicating whether or not the lexer language has embedded lexers.
*/
bool multilang = false;
/**
* The list of style numbers considered to be whitespace styles.
* This is used in multi-language lexers when backtracking to whitespace to
* determine which lexer grammar to use.
*/
bool ws[STYLE_MAX + 1];
/** List of known lexer names. */
std::set<std::string> lexerNames;
/** Style name to return for `NameOfStyle()`. */
std::string styleName;
/**
* Searches the given directory for lexers and records their names.
* @param path Path to a directory containing lexers.
*/
void ReadLexerNames(const char *path);
/**
* Logs the given error message or a Lua error message, prints it, and clears
* the stack.
* Error messages are logged to the LexerErrorKey property.
* @param L The Lua State.
* @param str The error message to log and print. If `nullptr`, logs and
* prints the Lua error message at the top of the stack.
*/
void LogError(lua_State *L, const char *str = nullptr);
/**
* Parses the given style string to set the properties for the given style
* number.
* Style strings mimic SciTE's "style.*.stylenumber" properties.
* (https://scintilla.org/SciTEDoc.html)
* @param num The style number to set properties for.
* @param style The style string containing properties to set.
*/
void SetStyle(int num, const char *style);
/**
* Iterates through the lexer's `_TOKENSTYLES`, setting the style properties
* for all defined styles.
*/
void SetStyles();
/**
* Initializes the lexer once the LexerHomeKey and LexerNameKey properties are
* set.
*/
bool Init();
/**
* When *lparam* is `0`, returns the size of the buffer needed to store the
* given string *str* in; otherwise copies *str* into the buffer *lparam* and
* returns the number of bytes copied.
* @param lparam `0` to get the number of bytes needed to store *str* or a
* pointer to a buffer large enough to copy *str* into.
* @param str The string to copy.
* @return number of bytes needed to hold *str*
*/
void *StringResult(long lparam, const char *str);
public:
/** Constructor. */
LexerLPeg();
/** Destructor. */
virtual ~LexerLPeg() = default;
/** Destroys the lexer object. */
void SCI_METHOD Release() override;
/**
* Lexes the Scintilla document.
* @param startPos The position in the document to start lexing at.
* @param lengthDoc The number of bytes in the document to lex.
* @param initStyle The initial style at position *startPos* in the document.
* @param buffer The document interface.
*/
void SCI_METHOD Lex(
Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle,
IDocument *buffer) override;
/**
* Folds the Scintilla document.
* @param startPos The position in the document to start folding at.
* @param lengthDoc The number of bytes in the document to fold.
* @param initStyle The initial style at position *startPos* in the document.
* @param buffer The document interface.
*/
void SCI_METHOD Fold(
Sci_PositionU startPos, Sci_Position lengthDoc, int, IDocument *buffer)
override;
/**
* Sets the *key* lexer property to *value*.
* If *key* starts with "style.", also set the style for the token.
* @param key The string property key.
* @param val The string value.
*/
Sci_Position SCI_METHOD PropertySet(
const char *key, const char *value) override;
/**
* Allows for direct communication between the application and the lexer.
* The application uses this to set `SS`, `sci`, `L`, and lexer properties,
* and to retrieve style names.
* @param code The communication code.
* @param arg The argument.
* @return void *data
*/
void * SCI_METHOD PrivateCall(int code, void *arg) override;
/**
* Returns the style name for the given style number.
* Note: the returned pointer is not guaranteed to exist after the next call
* to `NameOfStyle()`, so its contents should be immediately copied.
* @param style The style number to get the style name for.
* @return style name or nullptr
*/
const char * SCI_METHOD NameOfStyle(int style) override;
/**
* Returns the lexer property for *key*.
* @param key The string property key.
*/
const char * SCI_METHOD PropertyGet(const char *key) override;
/** Constructs a new instance of the lexer. */
static ILexer *LexerFactoryLPeg();
};
/** Lua pcall error message handler that adds a traceback. */
static int lua_error_handler(lua_State *L) {
luaL_traceback(L, L, lua_tostring(L, -1), 1);
return 1;
}
/** lexer.property[key] metamethod. */
static int lexer_property_index(lua_State *L) {
const char *property = lua_tostring(L, lua_upvalueindex(1));
lua_getfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
LexerLPeg *lexer = reinterpret_cast<LexerLPeg *>(lua_touserdata(L, -1));
lua_rawgetp(L, LUA_REGISTRYINDEX, lua_touserdata(L, -1));
lua_getfield(L, -1, "_BUFFER");
auto buffer = static_cast<IDocument *>(lua_touserdata(L, -1));
if (strcmp(property, "fold_level") == 0) {
luaL_argcheck(L, buffer, 1, "must be lexing or folding");
lua_pushinteger(L, buffer->GetLevel(luaL_checkinteger(L, 2) - 1));
} else if (strcmp(property, "indent_amount") == 0) {
luaL_argcheck(L, buffer, 1, "must be lexing or folding");
lua_pushinteger(L, buffer->GetLineIndentation(luaL_checkinteger(L, 2) - 1));
} else if (strcmp(property, "property") == 0) {
lua_pushstring(L, lexer->PropertyGet(luaL_checkstring(L, 2)));
} else if (strcmp(property, "property_int") == 0) {
lua_pushstring(L, lexer->PropertyGet(luaL_checkstring(L, 2)));
lua_pushinteger(L, lua_tointeger(L, -1));
} else if (strcmp(property, "style_at") == 0) {
luaL_argcheck(L, buffer, 1, "must be lexing or folding");
int style = buffer->StyleAt(luaL_checkinteger(L, 2) - 1);
lua_getfield(L, 4, "_TOKENSTYLES");
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1))
if (luaL_checkinteger(L, -1) - 1 == style) break;
lua_pop(L, 1); // style_num, leaving name on top
} else if (strcmp(property, "line_state") == 0) {
luaL_argcheck(L, buffer, 1, "must be lexing or folding");
lua_pushinteger(L, buffer->GetLineState(luaL_checkinteger(L, 2) - 1));
}
return 1;
}
/** lexer.property[key] = value metamethod. */
static int lexer_property_newindex(lua_State *L) {
const char *property = lua_tostring(L, lua_upvalueindex(1));
luaL_argcheck(
L, strcmp(property, "fold_level") != 0 &&
strcmp(property, "indent_amount") != 0 &&
strcmp(property, "property_int") != 0 &&
strcmp(property, "style_at") != 0 &&
strcmp(property, "line_from_position") != 0, 3, "read-only property");
lua_getfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
LexerLPeg *lexer = reinterpret_cast<LexerLPeg *>(lua_touserdata(L, -1));
lua_rawgetp(L, LUA_REGISTRYINDEX, lua_touserdata(L, -1));
if (strcmp(property, "property") == 0)
lexer->PropertySet(luaL_checkstring(L, 2), luaL_checkstring(L, 3));
else if (strcmp(property, "line_state") == 0) {
luaL_argcheck(
L, lua_getfield(L, -1, "_BUFFER"), 1, "must be lexing or folding");
auto buffer = static_cast<IDocument *>(lua_touserdata(L, -1));
buffer->SetLineState(luaL_checkinteger(L, 2) - 1, luaL_checkinteger(L, 3));
}
return 0;
}
/** The lexer's `line_from_position` Lua function. */
static int line_from_position(lua_State *L) {
auto buffer = static_cast<IDocument *>(
lua_touserdata(L, lua_upvalueindex(1)));
lua_pushinteger(L, buffer->LineFromPosition(luaL_checkinteger(L, 1) - 1) + 1);
return 1;
}
/** lexer.property metamethod. */
static int lexer_index(lua_State *L) {
const char *key = lua_tostring(L, 2);
if (strcmp(key, "fold_level") == 0 || strcmp(key, "indent_amount") == 0 ||
strcmp(key, "property") == 0 || strcmp(key, "property_int") == 0 ||
strcmp(key, "style_at") == 0 || strcmp(key, "line_state") == 0) {
lua_newtable(L);
lua_createtable(L, 0, 2);
lua_pushvalue(L, 2), lua_pushcclosure(L, lexer_property_index, 1);
lua_setfield(L, -2, "__index");
lua_pushvalue(L, 2), lua_pushcclosure(L, lexer_property_newindex, 1);
lua_setfield(L, -2, "__newindex");
lua_setmetatable(L, -2);
} else if (strcmp(key, "line_from_position") == 0) {
lua_getfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
lua_rawgetp(L, LUA_REGISTRYINDEX, lua_touserdata(L, -1));
luaL_argcheck(
L, lua_getfield(L, -1, "_BUFFER"), 2, "must be lexing or folding");
lua_pushcclosure(L, line_from_position, 1);
} else if (strncmp(key, "fold", 4) == 0) {
// Alias lexer.fold* to lexer.property['fold*'].
if (strcmp(key, "folding") == 0) key = "fold"; // lexer.fold() exists
lua_getfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
LexerLPeg *lexer = reinterpret_cast<LexerLPeg *>(lua_touserdata(L, -1));
const char *value = lexer->PropertyGet(luaL_gsub(L, key, "_", "."));
lua_pushboolean(L, strcmp(value, "1") == 0);
} else lua_rawget(L, 1);
return 1;
}
/** lexer.property = value metamethod. */
static int lexer_newindex(lua_State *L) {
const char *key = lua_tostring(L, 2);
luaL_argcheck(
L, strcmp(key, "fold_level") != 0 && strcmp(key, "indent_amount") != 0 &&
strcmp(key, "property") != 0 && strcmp(key, "property_int") != 0 &&
strcmp(key, "style_at") != 0 && strcmp(key, "line_state") != 0 &&
strcmp(key, "line_from_position") != 0, 3, "read-only property");
if (strncmp(key, "fold", 4) == 0 && strcmp(key, "fold_level") != 0) {
// Alias lexer.fold* to lexer.property['fold*'].
if (strcmp(key, "folding") == 0) key = "fold"; // lexer.fold() exists
key = luaL_gsub(L, key, "_", ".");
lua_getfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
LexerLPeg *lexer = reinterpret_cast<LexerLPeg *>(lua_touserdata(L, -1));
if (lua_toboolean(L, 3))
lexer->PropertySet(
key, (!lua_isnumber(L, 3) || lua_tonumber(L, 3) == 1) ? "1" : "0");
else
lexer->PropertySet(key, "0");
} else lua_rawset(L, 1);
return 0;
}
/**
* Replaces the string property key the top of the stack with its expanded
* value.
* Invokes `lexer.property_expanded[]` to perform the expansion.
* @param L The Lua State.
*/
static void expand_property(lua_State *L) {
RECORD_STACK_TOP(L);
lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"), lua_getfield(L, -1, "lexer");
lua_getfield(L, -1, "property_expanded");
lua_pushvalue(L, -4), lua_gettable(L, -2), lua_replace(L, -5);
lua_pop(L, 3); // property_expanded, lexer, _LOADED
ASSERT_STACK_TOP(L);
}
void LexerLPeg::ReadLexerNames(const char *path) {
#if !_WIN32
DIR *dir = opendir(path);
if (!dir) return;
struct dirent *entry;
while ((entry = readdir(dir))) {
char *p = strstr(entry->d_name, ".lua");
if (p) lexerNames.emplace(entry->d_name, p - entry->d_name);
}
closedir(dir);
#else
struct _finddata_t file;
std::string glob(path);
glob += "/*";
intptr_t handle = _findfirst(glob.c_str(), &file);
if (handle == -1) return;
do {
char *p = strstr(file.name, ".lua");
if (p) lexerNames.emplace(file.name, p - file.name);
} while (_findnext(handle, &file) != -1);
_findclose(handle);
#endif
}
void LexerLPeg::LogError(lua_State *L, const char *str) {
const char *value = str ? str : lua_tostring(L, -1);
PropertySet(LexerErrorKey, value);
fprintf(stderr, "Lua Error: %s.\n", value);
lua_settop(L, 0);
}
void LexerLPeg::SetStyle(int num, const char *style) {
auto style_copy = static_cast<char *>(malloc(strlen(style) + 1));
char *key = strcpy(style_copy, style), *next = nullptr, *val = nullptr;
while (key) {
if ((next = strchr(key, ','))) *next++ = '\0';
if ((val = strchr(key, ':'))) *val++ = '\0';
if (strcmp(key, "font") == 0 && val)
SS(sci, SCI_STYLESETFONT, num, reinterpret_cast<sptr_t>(val));
else if (strcmp(key, "size") == 0 && val)
SS(sci, SCI_STYLESETSIZE, num, static_cast<int>(atoi(val)));
else if (strcmp(key, "bold") == 0 || strcmp(key, "notbold") == 0 ||
strcmp(key, "weight") == 0) {
#if !CURSES
int weight = SC_WEIGHT_NORMAL;
if (*key == 'b')
weight = SC_WEIGHT_BOLD;
else if (*key == 'w' && val)
weight = atoi(val);
SS(sci, SCI_STYLESETWEIGHT, num, weight);
#else
// Scintilla curses requires font attributes to be stored in the "font
// weight" style attribute.
// First, clear any existing SC_WEIGHT_NORMAL, SC_WEIGHT_SEMIBOLD, or
// SC_WEIGHT_BOLD values stored in the lower 16 bits. Then set the
// appropriate curses attr.
sptr_t weight =
SS(sci, SCI_STYLEGETWEIGHT, num, 0) & ~(A_COLOR | A_CHARTEXT);
int bold =
*key == 'b' || (*key == 'w' && val && atoi(val) > SC_WEIGHT_NORMAL);
SS(
sci, SCI_STYLESETWEIGHT, num,
bold ? weight | A_BOLD : weight & ~A_BOLD);
#endif
} else if (strcmp(key, "italics") == 0 || strcmp(key, "notitalics") == 0)
SS(sci, SCI_STYLESETITALIC, num, *key == 'i');
else if (strcmp(key, "underlined") == 0 ||
strcmp(key, "notunderlined") == 0) {
#if !CURSES
SS(sci, SCI_STYLESETUNDERLINE, num, *key == 'u');
#else
// Scintilla curses requires font attributes to be stored in the "font
// weight" style attribute.
// First, clear any existing SC_WEIGHT_NORMAL, SC_WEIGHT_SEMIBOLD, or
// SC_WEIGHT_BOLD values stored in the lower 16 bits. Then set the
// appropriate curses attr.
sptr_t weight =
SS(sci, SCI_STYLEGETWEIGHT, num, 0) & ~(A_COLOR | A_CHARTEXT);
SS(
sci, SCI_STYLESETWEIGHT, num,
(*key == 'u') ? weight | A_UNDERLINE : weight & ~A_UNDERLINE);
#endif
} else if ((strcmp(key, "fore") == 0 || strcmp(key, "back") == 0) &&
val) {
int msg = (*key == 'f') ? SCI_STYLESETFORE : SCI_STYLESETBACK;
int color = static_cast<int>(strtol(val, nullptr, 0));
if (*val == '#') { // #RRGGBB format; Scintilla format is 0xBBGGRR
color = static_cast<int>(strtol(val + 1, nullptr, 16));
color =
((color & 0xFF0000) >> 16) | (color & 0xFF00) |
((color & 0xFF) << 16); // convert to 0xBBGGRR
}
SS(sci, msg, num, color);
} else if (strcmp(key, "eolfilled") == 0 ||
strcmp(key, "noteolfilled") == 0)
SS(sci, SCI_STYLESETEOLFILLED, num, *key == 'e');
else if (strcmp(key, "characterset") == 0 && val)
SS(sci, SCI_STYLESETCHARACTERSET, num, static_cast<int>(atoi(val)));
else if (strcmp(key, "case") == 0 && val) {
if (*val == 'u')
SS(sci, SCI_STYLESETCASE, num, SC_CASE_UPPER);
else if (*val == 'l')
SS(sci, SCI_STYLESETCASE, num, SC_CASE_LOWER);
} else if (strcmp(key, "visible") == 0 || strcmp(key, "notvisible") == 0)
SS(sci, SCI_STYLESETVISIBLE, num, *key == 'v');
else if (strcmp(key, "changeable") == 0 ||
strcmp(key, "notchangeable") == 0)
SS(sci, SCI_STYLESETCHANGEABLE, num, *key == 'c');
else if (strcmp(key, "hotspot") == 0 || strcmp(key, "nothotspot") == 0)
SS(sci, SCI_STYLESETHOTSPOT, num, *key == 'h');
key = next;
}
free(style_copy);
}
void LexerLPeg::SetStyles() {
RECORD_STACK_TOP(L);
// If the lexer defines additional styles, set their properties first (if
// the user has not already defined them).
lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
lua_getfield(L, -1, "_EXTRASTYLES");
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1))
if (lua_isstring(L, -2) && lua_isstring(L, -1)) {
lua_pushstring(L, "style."), lua_pushvalue(L, -3), lua_concat(L, 2);
if (!*props.Get(lua_tostring(L, -1)))
PropertySet(lua_tostring(L, -1), lua_tostring(L, -2));
lua_pop(L, 1); // style name
}
lua_pop(L, 1); // _EXTRASTYLES
if (!SS || !sci) {
lua_pop(L, 1); // lexer object
// Skip, but do not report an error since `reinit` would remain `false`
// and subsequent calls to `Lex()` and `Fold()` would repeatedly call this
// function and error.
ASSERT_STACK_TOP(L);
return;
}
lua_pushstring(L, "style.default"), expand_property(L);
SetStyle(STYLE_DEFAULT, lua_tostring(L, -1));
lua_pop(L, 1); // style
SS(sci, SCI_STYLECLEARALL, 0, 0); // set default styles
lua_getfield(L, -1, "_TOKENSTYLES");
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1))
if (lua_isstring(L, -2) && lua_isnumber(L, -1) &&
lua_tointeger(L, -1) - 1 != STYLE_DEFAULT) {
lua_pushstring(L, "style."), lua_pushvalue(L, -3), lua_concat(L, 2);
expand_property(L);
SetStyle(lua_tointeger(L, -2) - 1, lua_tostring(L, -1));
lua_pop(L, 1); // style
}
lua_pop(L, 2); // _TOKENSTYLES, lexer object
ASSERT_STACK_TOP(L);
}
bool LexerLPeg::Init() {
if (!props.GetExpanded(LexerHomeKey, nullptr) ||
!*props.Get(LexerNameKey) || !L)
return false;
char *_home = reinterpret_cast<char *>(
malloc(props.GetExpanded(LexerHomeKey, nullptr) + 1));
props.GetExpanded(LexerHomeKey, _home);
std::string home(_home);
free(_home);
const char *lexer = props.Get(LexerNameKey);
RECORD_STACK_TOP(L);
// Designate the currently running LexerLPeg instance.
// This needs to be done prior to calling any Lua lexer code, particularly
// when `ownLua` is `false`, as there may be multiple LexerLPeg instances
// floating around, and the lexer module methods and metamethods need to
// know which instance to use.
lua_pushlightuserdata(L, reinterpret_cast<void *>(this));
lua_setfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
// Determine where to look for the lexer module and themes.
std::vector<std::string> dirs;
size_t start = 0, end;
while ((end = home.find(';', start)) != std::string::npos) {
dirs.emplace_back(home, start, end - start);
start = end + 1;
}
dirs.emplace_back(home, start);
// If necessary, load the lexer module.
lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED");
if (lua_getfield(L, -1, "lexer") == LUA_TNIL) {
for (const std::string& dir : dirs) {
lua_pushstring(L, dir.c_str());
lua_pushstring(L, "/lexer.lua");
lua_concat(L, 2);
int status = luaL_loadfile(L, lua_tostring(L, -1));
if (status == LUA_ERRFILE) {
lua_pop(L, 2); // error message, filename
continue; // try next directory
}
lua_remove(L, -2); // filename
lua_pushcfunction(L, lua_error_handler);
lua_insert(L, -2);
if (status == LUA_OK && lua_pcall(L, 0, 1, -2) == LUA_OK) break;
return (LogError(L), false);
}
if (lua_isnil(L, -1))
return (LogError(L, "'lexer.lua' module not found"), false);
lua_remove(L, -2); // lua_error_handler
lua_replace(L, -2); // nil
lua_pushinteger(L, SC_FOLDLEVELBASE);
lua_setfield(L, -2, "FOLD_BASE");
lua_pushinteger(L, SC_FOLDLEVELWHITEFLAG);
lua_setfield(L, -2, "FOLD_BLANK");
lua_pushinteger(L, SC_FOLDLEVELHEADERFLAG);
lua_setfield(L, -2, "FOLD_HEADER");
lua_createtable(L, 0, 2);
lua_pushcfunction(L, lexer_index), lua_setfield(L, -2, "__index");
lua_pushcfunction(L, lexer_newindex), lua_setfield(L, -2, "__newindex");
lua_setmetatable(L, -2);
lua_pushvalue(L, -1), lua_setfield(L, -3, "lexer");
}
lua_replace(L, -2);
// Update the userdata needed by lexer metamethods.
lua_pushvalue(L, -1);
lua_rawsetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
// Load the language lexer.
if (lua_getfield(L, -1, "load") != LUA_TFUNCTION)
return (LogError(L, "'lexer.load' function not found"), false);
lua_pushcfunction(L, lua_error_handler), lua_insert(L, -2);
lua_pushstring(L, lexer), lua_pushnil(L), lua_pushboolean(L, 1);
if (lua_pcall(L, 3, 1, -5) != LUA_OK) return (LogError(L), false);
lua_remove(L, -2); // lua_error_handler
lua_remove(L, -2); // lexer module
lua_rawsetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
// Load the theme and set up styles.
if (props.GetExpanded(LexerThemeKey, nullptr)) {
char *theme = reinterpret_cast<char *>(
malloc(props.GetExpanded(LexerThemeKey, nullptr) + 1));
props.GetExpanded(LexerThemeKey, theme);
if (!strstr(theme, "/") && !strstr(theme, "\\")) { // theme name
for (const std::string& dir : dirs) {
lua_pushstring(L, dir.c_str());
lua_pushstring(L, "/themes/");
lua_pushstring(L, theme);
lua_pushstring(L, ".lua");
lua_concat(L, 4);
if (luaL_loadfile(L, lua_tostring(L, -1)) != LUA_ERRFILE ||
dir == dirs.back()) {
lua_pop(L, 1); // function, leaving filename on top
break;
}
lua_pop(L, 2); // error message, filename
}
} else lua_pushstring(L, theme); // path to theme
lua_pushcfunction(L, lua_error_handler);
lua_insert(L, -2);
if (luaL_loadfile(L, lua_tostring(L, -1)) == LUA_OK &&
lua_pcall(L, 0, 0, -3) == LUA_OK)
lua_pop(L, 2); // theme, lua_error_handler
else
LogError(L);
free(theme);
}
SetStyles();
// If the lexer is a parent, it will have children in its _CHILDREN table.
// In that case, determine which styles are language whitespace styles
// ([lang]_whitespace). This is necessary for determining which language
// to start lexing with.
lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
if (lua_getfield(L, -1, "_CHILDREN") == LUA_TTABLE) {
multilang = true;
for (int i = 0; i <= STYLE_MAX; i++)
ws[i] = strstr(NameOfStyle(i), "whitespace") ? true : false;
}
lua_pop(L, 2); // _CHILDREN, lexer object
reinit = false;
PropertySet(LexerErrorKey, "");
ASSERT_STACK_TOP(L);
return true;
}
void *LexerLPeg::StringResult(long lparam, const char *str) {
if (lparam) strcpy(reinterpret_cast<char *>(lparam), str);
return reinterpret_cast<void *>(strlen(str));
}
LexerLPeg::LexerLPeg() : DefaultLexer("lpeg", SCLEX_LPEG), L(luaL_newstate()) {
// Initialize the Lua state, load libraries, and set platform variables.
if (!L) {
fprintf(stderr, "Lua failed to initialize.\n");
return;
}
#if LUA_VERSION_NUM < 502
luaL_requiref(L, "", luaopen_base, 1), lua_pop(L, 1);
#else
luaL_requiref(L, "_G", luaopen_base, 1), lua_pop(L, 1);
#endif
luaL_requiref(L, LUA_TABLIBNAME, luaopen_table, 1), lua_pop(L, 1);
luaL_requiref(L, LUA_STRLIBNAME, luaopen_string, 1), lua_pop(L, 1);
// TODO: figure out why lua_setglobal() is needed for lpeg.
luaL_requiref(L, "lpeg", luaopen_lpeg, 1), lua_setglobal(L, "lpeg");
#if _WIN32
lua_pushboolean(L, 1), lua_setglobal(L, "WIN32");
#endif
#if __APPLE__
lua_pushboolean(L, 1), lua_setglobal(L, "OSX");
#endif
#if GTK
lua_pushboolean(L, 1), lua_setglobal(L, "GTK");
#endif
#if CURSES
lua_pushboolean(L, 1), lua_setglobal(L, "CURSES");
#endif
}
void SCI_METHOD LexerLPeg::Release() {
if (ownLua && L)
lua_close(L);
else if (!ownLua) {
lua_pushnil(L);
lua_rawsetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
lua_pushnil(L), lua_setfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
}
delete this;
}
void SCI_METHOD LexerLPeg::Lex(
Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle,
IDocument *buffer)
{
LexAccessor styler(buffer);
if ((reinit && !Init()) || !L) {
// Style everything in the default style.
styler.StartAt(startPos);
styler.StartSegment(startPos);
styler.ColourTo(startPos + lengthDoc - 1, STYLE_DEFAULT);
styler.Flush();
return;
}
RECORD_STACK_TOP(L);
lua_pushlightuserdata(L, reinterpret_cast<void *>(this));
lua_setfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
lua_pushlightuserdata(L, reinterpret_cast<void *>(buffer));
lua_setfield(L, -2, "_BUFFER");
// Ensure the lexer has a grammar.
// This could be done in the lexer module's `lex()`, but for large files,
// passing string arguments from C to Lua is expensive.
if (!lua_getfield(L, -1, "_GRAMMAR")) {
lua_pop(L, 2); // _GRAMMAR, lexer object
// Style everything in the default style.
styler.StartAt(startPos);
styler.StartSegment(startPos);
styler.ColourTo(startPos + lengthDoc - 1, STYLE_DEFAULT);
styler.Flush();
return;
} else lua_pop(L, 1); // _GRAMMAR
// Start from the beginning of the current style so LPeg matches it.
// For multilang lexers, start at whitespace since embedded languages have
// [lang]_whitespace styles. This is so LPeg can start matching child
// languages instead of parent ones if necessary.
if (startPos > 0) {
Sci_PositionU i = startPos;
while (i > 0 && styler.StyleAt(i - 1) == initStyle) i--;
if (multilang)
while (i > 0 && !ws[static_cast<size_t>(styler.StyleAt(i))]) i--;
lengthDoc += startPos - i, startPos = i;
}
if (lua_getfield(L, -1, "lex") != LUA_TFUNCTION)
return LogError(L, "'lexer.lex' function not found");
lua_pushcfunction(L, lua_error_handler), lua_insert(L, -2);
lua_pushvalue(L, -3);
lua_pushlstring(L, buffer->BufferPointer() + startPos, lengthDoc);
lua_pushinteger(L, styler.StyleAt(startPos) + 1);
if (lua_pcall(L, 3, 1, -5) != LUA_OK) return LogError(L);
if (!lua_istable(L, -1))
return LogError(L, "Table of tokens expected from 'lexer.lex'");
// Style the text from the token table returned.
int len = lua_rawlen(L, -1);
if (len > 0) {
int style = STYLE_DEFAULT;
styler.StartAt(startPos);
styler.StartSegment(startPos);
lua_getfield(L, -3, "_TOKENSTYLES");
// Loop through token-position pairs.
for (int i = 1; i < len; i += 2) {
style = STYLE_DEFAULT;
if (lua_rawgeti(L, -2, i), lua_rawget(L, -2))
style = lua_tointeger(L, -1) - 1;
lua_pop(L, 1); // _TOKENSTYLES[token]
lua_rawgeti(L, -2, i + 1); // pos
unsigned int position = lua_tointeger(L, -1) - 1;
lua_pop(L, 1); // pos
if (style >= 0 && style <= STYLE_MAX)
styler.ColourTo(startPos + position - 1, style);
else
lua_pushfstring(L, "Bad style number: %d", style), LogError(L);
if (position > startPos + lengthDoc) break;
}
lua_pop(L, 1); // _TOKENSTYLES
styler.ColourTo(startPos + lengthDoc - 1, style);
styler.Flush();
}
lua_pop(L, 3); // token table returned, lua_error_handler, lexer object
ASSERT_STACK_TOP(L);
}
void SCI_METHOD LexerLPeg::Fold(
Sci_PositionU startPos, Sci_Position lengthDoc, int, IDocument *buffer)
{
if ((reinit && !Init()) || !L) return;
RECORD_STACK_TOP(L);
lua_pushlightuserdata(L, reinterpret_cast<void *>(this));
lua_setfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
lua_pushlightuserdata(L, reinterpret_cast<void *>(buffer));
lua_setfield(L, -2, "_BUFFER");
LexAccessor styler(buffer);
if (lua_getfield(L, -1, "fold") != LUA_TFUNCTION)
return LogError(L, "'lexer.fold' function not found");
lua_pushcfunction(L, lua_error_handler), lua_insert(L, -2);
lua_pushvalue(L, -3);
Sci_Position currentLine = styler.GetLine(startPos);
lua_pushlstring(L, buffer->BufferPointer() + startPos, lengthDoc);
lua_pushinteger(L, startPos + 1);
lua_pushinteger(L, currentLine + 1);
lua_pushinteger(L, styler.LevelAt(currentLine) & SC_FOLDLEVELNUMBERMASK);
if (lua_pcall(L, 5, 1, -7) != LUA_OK) return LogError(L);
if (!lua_istable(L, -1))
return LogError(L, "Table of folds expected from 'lexer.fold'");
// Fold the text from the fold table returned.
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) // line = level
styler.SetLevel(lua_tointeger(L, -2) - 1, lua_tointeger(L, -1));
lua_pop(L, 3); // fold table returned, lua_error_handler, lexer object
ASSERT_STACK_TOP(L);
}
Sci_Position SCI_METHOD LexerLPeg::PropertySet(
const char *key, const char *value)
{
props.Set(key, value, strlen(key), strlen(value));
if (strcmp(key, LexerHomeKey) == 0 && lexerNames.empty())
ReadLexerNames(value); // not using SCI_LOADLEXERLIBRARY private call
if (reinit &&
(strcmp(key, LexerHomeKey) == 0 || strcmp(key, LexerNameKey) == 0))
Init();
else if (L && SS && sci && strncmp(key, "style.", 6) == 0) {
// The container is managing styles manually.
RECORD_STACK_TOP(L);
lua_pushlightuserdata(L, reinterpret_cast<void *>(this));
lua_setfield(L, LUA_REGISTRYINDEX, "sci_lexer_lpeg");
if (lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this))) {
lua_getfield(L, -1, "_TOKENSTYLES");
lua_pushstring(L, key + 6);
if (lua_rawget(L, -2) == LUA_TNUMBER) {
lua_pushstring(L, key), expand_property(L);
int style_num = lua_tointeger(L, -2) - 1;
SetStyle(style_num, lua_tostring(L, -1));
if (style_num == STYLE_DEFAULT)
// Assume a theme change, with the default style being set first.
// Subsequent style settings will be based on the default.
SS(sci, SCI_STYLECLEARALL, 0, 0);
lua_pop(L, 1); // style
}
lua_pop(L, 2); // style number, _TOKENSTYLES
}
lua_pop(L, 1); // lexer object or nil
ASSERT_STACK_TOP(L);
}
return -1; // no need to re-lex
}
void * SCI_METHOD LexerLPeg::PrivateCall(int code, void *arg) {
auto lParam = reinterpret_cast<sptr_t>(arg);
switch(code) {
case SCI_GETDIRECTFUNCTION:
SS = reinterpret_cast<SciFnDirect>(lParam);
return nullptr;
case SCI_SETDOCPOINTER:
sci = lParam;
return nullptr;
case SCI_CHANGELEXERSTATE:
if (ownLua) lua_close(L);
L = reinterpret_cast<lua_State *>(arg), ownLua = false;
return nullptr;
case SCI_LOADLEXERLIBRARY: {
const char *path = reinterpret_cast<const char*>(arg);
ReadLexerNames(path);
std::string home(props.Get(LexerHomeKey));
if (!home.empty()) home.push_back(';');
home.append(path);
PropertySet(LexerHomeKey, home.c_str());
return nullptr;
} case SCI_PROPERTYNAMES: {
std::stringstream names;
for (const std::string& name : lexerNames) names << name << '\n';
return StringResult(lParam, names.str().c_str());
} case SCI_SETLEXERLANGUAGE:
if (strcmp(
props.Get(LexerNameKey),
reinterpret_cast<const char *>(arg)) != 0) {
reinit = true;
PropertySet(LexerErrorKey, "");
PropertySet(LexerNameKey, reinterpret_cast<const char *>(arg));
} else if (L)
ownLua ? SetStyles() : static_cast<void>(Init());
return nullptr;
case SCI_GETLEXERLANGUAGE: {
if (!L) return StringResult(lParam, "null");
RECORD_STACK_TOP(L);
lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
lua_getfield(L, -1, "_NAME");
std::string val(lua_tostring(L, -1));
lua_pop(L, 2); // lexer name, lexer object
ASSERT_STACK_TOP(L);
if (!SS || !sci || !multilang) return StringResult(lParam, val.c_str());
val.push_back('/');
int pos = SS(sci, SCI_GETCURRENTPOS, 0, 0);
while (pos >= 0 && !ws[SS(sci, SCI_GETSTYLEAT, pos, 0)]) pos--;
if (pos >= 0) {
const char *name = NameOfStyle(SS(sci, SCI_GETSTYLEAT, pos, 0)), *p;
if (name && (p = strstr(name, "_whitespace"))) {
val.append(name, p - name);
return StringResult(lParam, val.c_str());
}
}
val.append(val, 0, val.length() - 1); // "lexer/lexer" fallback
return StringResult(lParam, val.c_str());
} case SCI_GETNAMEDSTYLES:
if (!L) return reinterpret_cast<void *>(STYLE_DEFAULT);
for (int i = 0; i < STYLE_MAX; i++)
if (strcmp(NameOfStyle(i), reinterpret_cast<const char *>(arg)) == 0)
return reinterpret_cast<void *>(i);
return reinterpret_cast<void *>(STYLE_DEFAULT);
case SCI_GETSTATUS:
return StringResult(lParam, props.Get(LexerErrorKey));
}
return nullptr;
}
const char * SCI_METHOD LexerLPeg::NameOfStyle(int style) {
if (style < 0 || style > STYLE_MAX || !L) return nullptr;
RECORD_STACK_TOP(L);
styleName = "Not Available";
lua_rawgetp(L, LUA_REGISTRYINDEX, reinterpret_cast<void *>(this));
lua_getfield(L, -1, "_TOKENSTYLES");
for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1))
if (lua_tointeger(L, -1) - 1 == style) {
styleName = lua_tostring(L, -2);
lua_pop(L, 2); // value and key
break;
}
lua_pop(L, 2); // _TOKENSTYLES, lexer object
ASSERT_STACK_TOP(L);
return styleName.c_str();
}
const char * SCI_METHOD LexerLPeg::PropertyGet(const char *key) {
return props.Get(key);
}
ILexer *LexerLPeg::LexerFactoryLPeg() { return new LexerLPeg(); }
LexerModule lmLPeg(SCLEX_LPEG, LexerLPeg::LexerFactoryLPeg, "lpeg");
#else
#include <stdlib.h>
#include <assert.h>
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "LexerModule.h"
using namespace Scintilla;
static void LPegLex(Sci_PositionU, Sci_Position, int, WordList*[], Accessor&) {
return;
}
LexerModule lmLPeg(SCLEX_LPEG, LPegLex, "lpeg");
#endif // LPEG_LEXER

View file

@ -26,11 +26,10 @@
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
#include "DefaultLexer.h"
#include "LexerBase.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
using namespace std;
@ -41,8 +40,15 @@ struct latexFoldSave {
latexFoldSave(const latexFoldSave &save) : structLev(save.structLev) {
for (int i = 0; i < 8; ++i) openBegins[i] = save.openBegins[i];
}
latexFoldSave &operator=(const latexFoldSave &save) {
if (this != &save) {
structLev = save.structLev;
for (int i = 0; i < 8; ++i) openBegins[i] = save.openBegins[i];
}
return *this;
}
int openBegins[8];
int structLev;
Sci_Position structLev;
};
class LexerLaTeX : public LexerBase {
@ -81,8 +87,16 @@ public:
static ILexer *LexerFactoryLaTeX() {
return new LexerLaTeX();
}
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess);
void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess);
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;
// ILexerWithIdentity methods
const char * SCI_METHOD GetName() override {
return "latex";
}
int SCI_METHOD GetIdentifier() override {
return SCLEX_LATEX;
}
};
static bool latexIsSpecial(int ch) {
@ -291,6 +305,8 @@ void SCI_METHOD LexerLaTeX::Lex(Sci_PositionU startPos, Sci_Position length, int
latexStateReset(mode, state);
if (latexLastWordIs(i, styler, "{verbatim}")) {
state = SCE_L_VERBATIM;
} else if (latexLastWordIs(i, styler, "{lstlisting}")) {
state = SCE_L_VERBATIM;
} else if (latexLastWordIs(i, styler, "{comment}")) {
state = SCE_L_COMMENT2;
} else if (latexLastWordIs(i, styler, "{math}") && mode == 0) {
@ -439,6 +455,9 @@ void SCI_METHOD LexerLaTeX::Lex(Sci_PositionU startPos, Sci_Position length, int
if (latexLastWordIs(match, styler, "{verbatim}")) {
styler.ColourTo(i - 1, state);
state = SCE_L_COMMAND;
} else if (latexLastWordIs(match, styler, "{lstlisting}")) {
styler.ColourTo(i - 1, state);
state = SCE_L_COMMAND;
}
}
}

View file

@ -24,9 +24,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
#define SCE_LISP_CHARACTER 29
#define SCE_LISP_MACRO 30

View file

@ -23,9 +23,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsAWordChar(const int ch) {
return (ch < 0x80) && (isalpha(ch) || ch == '@' || ch == '_');

View file

@ -14,10 +14,13 @@
#include <assert.h>
#include <ctype.h>
#include <string>
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
#include "StringCopy.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
@ -25,9 +28,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
// Test for [=[ ... ]=] delimiters, returns 0 if it's only a [ or ],
// return 1 for [[ or ]], returns >=2 for [=[ or ]=] and so on.
@ -48,14 +49,14 @@ static void ColouriseLuaDoc(
WordList *keywordlists[],
Accessor &styler) {
WordList &keywords = *keywordlists[0];
WordList &keywords2 = *keywordlists[1];
WordList &keywords3 = *keywordlists[2];
WordList &keywords4 = *keywordlists[3];
WordList &keywords5 = *keywordlists[4];
WordList &keywords6 = *keywordlists[5];
WordList &keywords7 = *keywordlists[6];
WordList &keywords8 = *keywordlists[7];
const WordList &keywords = *keywordlists[0];
const WordList &keywords2 = *keywordlists[1];
const WordList &keywords3 = *keywordlists[2];
const WordList &keywords4 = *keywordlists[3];
const WordList &keywords5 = *keywordlists[4];
const WordList &keywords6 = *keywordlists[5];
const WordList &keywords7 = *keywordlists[6];
const WordList &keywords8 = *keywordlists[7];
// Accepts accented characters
CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
@ -77,20 +78,26 @@ static void ColouriseLuaDoc(
int stringWs = 0;
if (initStyle == SCE_LUA_LITERALSTRING || initStyle == SCE_LUA_COMMENT ||
initStyle == SCE_LUA_STRING || initStyle == SCE_LUA_CHARACTER) {
int lineState = styler.GetLineState(currentLine - 1);
const int lineState = styler.GetLineState(currentLine - 1);
nestLevel = lineState >> 9;
sepCount = lineState & 0xFF;
stringWs = lineState & 0x100;
}
// results of identifier/keyword matching
Sci_Position idenPos = 0;
Sci_Position idenWordPos = 0;
int idenStyle = SCE_LUA_IDENTIFIER;
bool foundGoto = false;
// Do not leak onto next line
if (initStyle == SCE_LUA_STRINGEOL || initStyle == SCE_LUA_COMMENTLINE || initStyle == SCE_LUA_PREPROCESSOR) {
initStyle = SCE_LUA_DEFAULT;
}
StyleContext sc(startPos, length, initStyle, styler);
if (startPos == 0 && sc.ch == '#') {
// shbang line: # is a comment only if first char of the script
if (startPos == 0 && sc.ch == '#' && sc.chNext == '!') {
// shbang line: "#!" is a comment only if located at the start of the script
sc.SetState(SCE_LUA_COMMENTLINE);
}
for (; sc.More(); sc.Forward()) {
@ -178,40 +185,32 @@ static void ColouriseLuaDoc(
sc.SetState(SCE_LUA_DEFAULT);
}
} else if (sc.state == SCE_LUA_IDENTIFIER) {
if (!(setWord.Contains(sc.ch) || sc.ch == '.') || sc.Match('.', '.')) {
char s[100];
sc.GetCurrent(s, sizeof(s));
if (keywords.InList(s)) {
sc.ChangeState(SCE_LUA_WORD);
if (strcmp(s, "goto") == 0) { // goto <label> forward scan
sc.SetState(SCE_LUA_DEFAULT);
while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd)
sc.Forward();
if (setWordStart.Contains(sc.ch)) {
sc.SetState(SCE_LUA_LABEL);
sc.Forward();
while (setWord.Contains(sc.ch))
sc.Forward();
sc.GetCurrent(s, sizeof(s));
if (keywords.InList(s))
sc.ChangeState(SCE_LUA_WORD);
}
sc.SetState(SCE_LUA_DEFAULT);
}
} else if (keywords2.InList(s)) {
sc.ChangeState(SCE_LUA_WORD2);
} else if (keywords3.InList(s)) {
sc.ChangeState(SCE_LUA_WORD3);
} else if (keywords4.InList(s)) {
sc.ChangeState(SCE_LUA_WORD4);
} else if (keywords5.InList(s)) {
sc.ChangeState(SCE_LUA_WORD5);
} else if (keywords6.InList(s)) {
sc.ChangeState(SCE_LUA_WORD6);
} else if (keywords7.InList(s)) {
sc.ChangeState(SCE_LUA_WORD7);
} else if (keywords8.InList(s)) {
sc.ChangeState(SCE_LUA_WORD8);
idenPos--; // commit already-scanned identitier/word parts
if (idenWordPos > 0) {
idenWordPos--;
sc.ChangeState(idenStyle);
sc.ForwardBytes(idenWordPos);
idenPos -= idenWordPos;
if (idenPos > 0) {
sc.SetState(SCE_LUA_IDENTIFIER);
sc.ForwardBytes(idenPos);
}
} else {
sc.ForwardBytes(idenPos);
}
sc.SetState(SCE_LUA_DEFAULT);
if (foundGoto) { // goto <label> forward scan
while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd)
sc.Forward();
if (setWordStart.Contains(sc.ch)) {
sc.SetState(SCE_LUA_LABEL);
sc.Forward();
while (setWord.Contains(sc.ch))
sc.Forward();
char s[100];
sc.GetCurrent(s, sizeof(s));
if (keywords.InList(s)) // labels cannot be keywords
sc.ChangeState(SCE_LUA_WORD);
}
sc.SetState(SCE_LUA_DEFAULT);
}
@ -257,7 +256,7 @@ static void ColouriseLuaDoc(
}
} else if (sc.state == SCE_LUA_LITERALSTRING || sc.state == SCE_LUA_COMMENT) {
if (sc.ch == '[') {
int sep = LongDelimCheck(sc);
const int sep = LongDelimCheck(sc);
if (sep == 1 && sepCount == 1) { // [[-only allowed to nest
nestLevel++;
sc.Forward();
@ -285,6 +284,66 @@ static void ColouriseLuaDoc(
sc.Forward();
}
} else if (setWordStart.Contains(sc.ch)) {
// For matching various identifiers with dots and colons, multiple
// matches are done as identifier segments are added. Longest match is
// set to a word style. The non-matched part is in identifier style.
std::string ident;
idenPos = 0;
idenWordPos = 0;
idenStyle = SCE_LUA_IDENTIFIER;
foundGoto = false;
int cNext;
do {
int c;
const Sci_Position idenPosOld = idenPos;
std::string identSeg;
identSeg += static_cast<char>(sc.GetRelative(idenPos++));
while (setWord.Contains(c = sc.GetRelative(idenPos))) {
identSeg += static_cast<char>(c);
idenPos++;
}
if (keywords.InList(identSeg.c_str()) && (idenPosOld > 0)) {
idenPos = idenPosOld - 1; // keywords cannot mix
ident.pop_back();
break;
}
ident += identSeg;
const char* s = ident.c_str();
int newStyle = SCE_LUA_IDENTIFIER;
if (keywords.InList(s)) {
newStyle = SCE_LUA_WORD;
} else if (keywords2.InList(s)) {
newStyle = SCE_LUA_WORD2;
} else if (keywords3.InList(s)) {
newStyle = SCE_LUA_WORD3;
} else if (keywords4.InList(s)) {
newStyle = SCE_LUA_WORD4;
} else if (keywords5.InList(s)) {
newStyle = SCE_LUA_WORD5;
} else if (keywords6.InList(s)) {
newStyle = SCE_LUA_WORD6;
} else if (keywords7.InList(s)) {
newStyle = SCE_LUA_WORD7;
} else if (keywords8.InList(s)) {
newStyle = SCE_LUA_WORD8;
}
if (newStyle != SCE_LUA_IDENTIFIER) {
idenStyle = newStyle;
idenWordPos = idenPos;
}
if (idenStyle == SCE_LUA_WORD) // keywords cannot mix
break;
cNext = sc.GetRelative(idenPos + 1);
if ((c == '.' || c == ':') && setWordStart.Contains(cNext)) {
ident += static_cast<char>(c);
idenPos++;
} else {
cNext = 0;
}
} while (cNext);
if ((idenStyle == SCE_LUA_WORD) && (ident.compare("goto") == 0)) {
foundGoto = true;
}
sc.SetState(SCE_LUA_IDENTIFIER);
} else if (sc.ch == '\"') {
sc.SetState(SCE_LUA_STRING);
@ -322,48 +381,26 @@ static void ColouriseLuaDoc(
}
}
if (setWord.Contains(sc.chPrev) || sc.chPrev == '.') {
char s[100];
sc.GetCurrent(s, sizeof(s));
if (keywords.InList(s)) {
sc.ChangeState(SCE_LUA_WORD);
} else if (keywords2.InList(s)) {
sc.ChangeState(SCE_LUA_WORD2);
} else if (keywords3.InList(s)) {
sc.ChangeState(SCE_LUA_WORD3);
} else if (keywords4.InList(s)) {
sc.ChangeState(SCE_LUA_WORD4);
} else if (keywords5.InList(s)) {
sc.ChangeState(SCE_LUA_WORD5);
} else if (keywords6.InList(s)) {
sc.ChangeState(SCE_LUA_WORD6);
} else if (keywords7.InList(s)) {
sc.ChangeState(SCE_LUA_WORD7);
} else if (keywords8.InList(s)) {
sc.ChangeState(SCE_LUA_WORD8);
}
}
sc.Complete();
}
static void FoldLuaDoc(Sci_PositionU startPos, Sci_Position length, int /* initStyle */, WordList *[],
Accessor &styler) {
Sci_PositionU lengthDoc = startPos + length;
const Sci_PositionU lengthDoc = startPos + length;
int visibleChars = 0;
Sci_Position lineCurrent = styler.GetLine(startPos);
int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
int levelCurrent = levelPrev;
char chNext = styler[startPos];
bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
int styleNext = styler.StyleAt(startPos);
for (Sci_PositionU i = startPos; i < lengthDoc; i++) {
char ch = chNext;
const char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
int style = styleNext;
const int style = styleNext;
styleNext = styler.StyleAt(i + 1);
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
const bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
if (style == SCE_LUA_WORD) {
if (ch == 'i' || ch == 'd' || ch == 'f' || ch == 'e' || ch == 'r' || ch == 'u') {
char s[10] = "";
@ -433,4 +470,33 @@ static const char * const luaWordListDesc[] = {
0
};
LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc, luaWordListDesc);
namespace {
LexicalClass lexicalClasses[] = {
// Lexer Lua SCLEX_LUA SCE_LUA_:
0, "SCE_LUA_DEFAULT", "default", "White space: Visible only in View Whitespace mode (or if it has a back colour)",
1, "SCE_LUA_COMMENT", "comment", "Block comment (Lua 5.0)",
2, "SCE_LUA_COMMENTLINE", "comment line", "Line comment",
3, "SCE_LUA_COMMENTDOC", "comment documentation", "Doc comment -- Not used in Lua (yet?)",
4, "SCE_LUA_NUMBER", "literal numeric", "Number",
5, "SCE_LUA_WORD", "keyword", "Keyword",
6, "SCE_LUA_STRING", "literal string", "(Double quoted) String",
7, "SCE_LUA_CHARACTER", "literal string character", "Character (Single quoted string)",
8, "SCE_LUA_LITERALSTRING", "literal string", "Literal string",
9, "SCE_LUA_PREPROCESSOR", "preprocessor", "Preprocessor (obsolete in Lua 4.0 and up)",
10, "SCE_LUA_OPERATOR", "operator", "Operators",
11, "SCE_LUA_IDENTIFIER", "identifier", "Identifier (everything else...)",
12, "SCE_LUA_STRINGEOL", "error literal string", "End of line where string is not closed",
13, "SCE_LUA_WORD2", "identifier", "Other keywords",
14, "SCE_LUA_WORD3", "identifier", "Other keywords",
15, "SCE_LUA_WORD4", "identifier", "Other keywords",
16, "SCE_LUA_WORD5", "identifier", "Other keywords",
17, "SCE_LUA_WORD6", "identifier", "Other keywords",
18, "SCE_LUA_WORD7", "identifier", "Other keywords",
19, "SCE_LUA_WORD8", "identifier", "Other keywords",
20, "SCE_LUA_LABEL", "label", "Labels",
};
}
LexerModule lmLua(SCLEX_LUA, ColouriseLuaDoc, "lua", FoldLuaDoc, luaWordListDesc, lexicalClasses, ELEMENTS(lexicalClasses));

View file

@ -1,7 +1,8 @@
// Scintilla source code edit control
// Encoding: UTF-8
/** @file LexMMIXAL.cxx
** Lexer for MMIX Assembler Language.
** Written by Christoph Hösler <christoph.hoesler@student.uni-tuebingen.de>
** Written by Christoph Hösler <christoph.hoesler@student.uni-tuebingen.de>
** For information about MMIX visit http://www-cs-faculty.stanford.edu/~knuth/mmix.html
**/
// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
@ -25,16 +26,14 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsAWordChar(const int ch) {
return (ch < 0x80) && (isalnum(ch) || ch == ':' || ch == '_');
}
inline bool isMMIXALOperator(char ch) {
static inline bool isMMIXALOperator(char ch) {
if (IsASCII(ch) && isalnum(ch))
return false;
if (ch == '+' || ch == '-' || ch == '|' || ch == '^' ||
@ -86,8 +85,6 @@ static void ColouriseMMIXALDoc(Sci_PositionU startPos, Sci_Position length, int
} else if (sc.state == SCE_MMIXAL_NUMBER) { // NUMBER
if (!isdigit(sc.ch)) {
if (IsAWordChar(sc.ch)) {
char s[100];
sc.GetCurrent(s, sizeof(s));
sc.ChangeState(SCE_MMIXAL_REF);
sc.SetState(SCE_MMIXAL_REF);
} else {
@ -100,12 +97,11 @@ static void ColouriseMMIXALDoc(Sci_PositionU startPos, Sci_Position length, int
}
} else if (sc.state == SCE_MMIXAL_REF) { // REF
if (!IsAWordChar(sc.ch) ) {
char s[100];
sc.GetCurrent(s, sizeof(s));
char s0[100];
sc.GetCurrent(s0, sizeof(s0));
const char *s = s0;
if (*s == ':') { // ignore base prefix for match
for (size_t i = 0; i != sizeof(s)-1; ++i) {
*(s+i) = *(s+i+1);
}
++s;
}
if (special_register.InList(s)) {
sc.ChangeState(SCE_MMIXAL_REGISTER);
@ -155,9 +151,7 @@ static void ColouriseMMIXALDoc(Sci_PositionU startPos, Sci_Position length, int
if (sc.state == SCE_MMIXAL_OPCODE_POST || // OPCODE_POST
sc.state == SCE_MMIXAL_OPERANDS) { // OPERANDS
if (sc.state == SCE_MMIXAL_OPERANDS && isspace(sc.ch)) {
if (!sc.atLineEnd) {
sc.SetState(SCE_MMIXAL_COMMENT);
}
sc.SetState(SCE_MMIXAL_COMMENT);
} else if (isdigit(sc.ch)) {
sc.SetState(SCE_MMIXAL_NUMBER);
} else if (IsAWordChar(sc.ch) || sc.Match('@')) {

View file

@ -27,9 +27,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static int GetLotLineState(std::string &line) {
if (line.length()) {

View file

@ -23,9 +23,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
#define KW_MSSQL_STATEMENTS 0
#define KW_MSSQL_DATA_TYPES 1

View file

@ -24,9 +24,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
/**
* Is it a core character (C isalpha(), exclamation and question mark)
@ -84,7 +82,7 @@ static inline bool IsAlNumSym(int ch) {
* \param startPos Where to start scanning
* \param length Where to scan to
* \param initStyle The style at the initial point, not used in this folder
* \param keywordslists The keywordslists, currently, number 5 is used
* \param keywordlists The keywordslists, currently, number 5 is used
* \param styler The styler
*/
static void ColouriseMagikDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
@ -330,7 +328,7 @@ static const char * const magikWordListDesc[] = {
*
* \param keywordslist The list of keywords that are scanned, they should only
* contain the start keywords, not the end keywords
* \param The actual keyword
* \param keyword The actual keyword
* \return 1 if it is a folding start-keyword, -1 if it is a folding end-keyword
* 0 otherwise
*/

View file

@ -23,9 +23,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool AtEOL(Accessor &styler, Sci_PositionU i) {
return (styler[i] == '\n') ||

View file

@ -51,9 +51,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsNewline(const int ch) {
return (ch == '\n' || ch == '\r');
@ -147,6 +145,7 @@ static void ColorizeMarkdownDoc(Sci_PositionU startPos, Sci_Position length, int
WordList **, Accessor &styler) {
Sci_PositionU endPos = startPos + length;
int precharCount = 0;
bool isLinkNameDetecting = false;
// Don't advance on a new loop iteration and retry at the same position.
// Useful in the corner case of having to start at the beginning file position
// in the default state.
@ -339,6 +338,27 @@ static void ColorizeMarkdownDoc(Sci_PositionU startPos, Sci_Position length, int
++precharCount;
}
// Any link
if (sc.state == SCE_MARKDOWN_LINK) {
if (sc.Match("](") && sc.GetRelative(-1) != '\\') {
sc.Forward(2);
isLinkNameDetecting = true;
}
else if (sc.Match("]:") && sc.GetRelative(-1) != '\\') {
sc.Forward(2);
sc.SetState(SCE_MARKDOWN_DEFAULT);
}
else if (!isLinkNameDetecting && sc.ch == ']' && sc.GetRelative(-1) != '\\') {
sc.Forward();
sc.SetState(SCE_MARKDOWN_DEFAULT);
}
else if (isLinkNameDetecting && sc.ch == ')' && sc.GetRelative(-1) != '\\') {
sc.Forward();
sc.SetState(SCE_MARKDOWN_DEFAULT);
isLinkNameDetecting = false;
}
}
// New state anywhere in doc
if (sc.state == SCE_MARKDOWN_DEFAULT) {
if (sc.atLineStart && sc.ch == '#') {
@ -346,38 +366,16 @@ static void ColorizeMarkdownDoc(Sci_PositionU startPos, Sci_Position length, int
freezeCursor = true;
}
// Links and Images
if (sc.Match("![") || sc.ch == '[') {
Sci_Position i = 0, j = 0, k = 0;
Sci_Position len = endPos - sc.currentPos;
while (i < len && (sc.GetRelative(++i) != ']' || sc.GetRelative(i - 1) == '\\'))
;
if (sc.GetRelative(i) == ']') {
j = i;
if (sc.GetRelative(++i) == '(') {
while (i < len && (sc.GetRelative(++i) != ')' || sc.GetRelative(i - 1) == '\\'))
;
if (sc.GetRelative(i) == ')')
k = i;
}
else if (sc.GetRelative(i) == '[' || sc.GetRelative(++i) == '[') {
while (i < len && (sc.GetRelative(++i) != ']' || sc.GetRelative(i - 1) == '\\'))
;
if (sc.GetRelative(i) == ']')
k = i;
}
}
// At least a link text
if (j) {
sc.SetState(SCE_MARKDOWN_LINK);
sc.Forward(j);
// Also has a URL or reference portion
if (k)
sc.Forward(k - j);
sc.ForwardSetState(SCE_MARKDOWN_DEFAULT);
}
if (sc.Match("![")) {
sc.SetState(SCE_MARKDOWN_LINK);
sc.Forward(2);
}
else if (sc.ch == '[' && sc.GetRelative(-1) != '\\') {
sc.SetState(SCE_MARKDOWN_LINK);
sc.Forward();
}
// Code - also a special case for alternate inside spacing
if (sc.Match("``") && sc.GetRelative(3) != ' ' && AtTermStart(sc)) {
else if (sc.Match("``") && sc.GetRelative(3) != ' ' && AtTermStart(sc)) {
sc.SetState(SCE_MARKDOWN_CODE2);
sc.Forward();
}

View file

@ -1,7 +1,8 @@
// Scintilla source code edit control
// Encoding: UTF-8
/** @file LexMatlab.cxx
** Lexer for Matlab.
** Written by José Fonseca
** Written by José Fonseca
**
** Changes by Christoph Dalitz 2003/12/04:
** - added support for Octave
@ -18,6 +19,9 @@
**
** Changes by John Donoghue 2016/11/15
** - update matlab code folding
**
** Changes by John Donoghue 2017/01/18
** - update matlab block comment detection
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
@ -40,9 +44,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static bool IsMatlabCommentChar(int c) {
return (c == '%') ;
@ -62,6 +64,7 @@ static int CheckKeywordFoldPoint(char *str) {
if (strcmp ("if", str) == 0 ||
strcmp ("for", str) == 0 ||
strcmp ("switch", str) == 0 ||
strcmp ("while", str) == 0 ||
strcmp ("try", str) == 0 ||
strcmp ("do", str) == 0 ||
strcmp ("parfor", str) == 0 ||
@ -73,6 +76,15 @@ static int CheckKeywordFoldPoint(char *str) {
return 0;
}
static bool IsSpaceToEOL(Sci_Position startPos, Accessor &styler) {
Sci_Position line = styler.GetLine(startPos);
Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
for (Sci_Position i = startPos; i < eol_pos; i++) {
char ch = styler[i];
if(!IsASpace(ch)) return false;
}
return true;
}
static void ColouriseMatlabOctaveDoc(
Sci_PositionU startPos, Sci_Position length, int initStyle,
@ -88,6 +100,9 @@ static void ColouriseMatlabOctaveDoc(
// of a string
bool transpose = false;
// count of brackets as boolean for when end could be an operator not a keyword
int allow_end_op = 0;
// approximate position of first non space character in a line
int nonSpaceColumn = -1;
// approximate column position of the current character in a line
@ -140,8 +155,12 @@ static void ColouriseMatlabOctaveDoc(
} else if (sc.state == SCE_MATLAB_KEYWORD) {
if (!isalnum(sc.ch) && sc.ch != '_') {
char s[100];
sc.GetCurrentLowered(s, sizeof(s));
sc.GetCurrent(s, sizeof(s));
if (keywords.InList(s)) {
if (strcmp ("end", s) == 0 && allow_end_op) {
sc.ChangeState(SCE_MATLAB_NUMBER);
}
sc.SetState(SCE_MATLAB_DEFAULT);
transpose = false;
} else {
@ -180,7 +199,7 @@ static void ColouriseMatlabOctaveDoc(
}
} else if (sc.state == SCE_MATLAB_COMMENT) {
// end or start of a nested a block comment?
if( IsCommentChar(sc.ch) && sc.chNext == '}' && nonSpaceColumn == column) {
if( IsCommentChar(sc.ch) && sc.chNext == '}' && nonSpaceColumn == column && IsSpaceToEOL(sc.currentPos+2, styler)) {
if(commentDepth > 0) commentDepth --;
curLine = styler.GetLine(sc.currentPos);
@ -192,7 +211,7 @@ static void ColouriseMatlabOctaveDoc(
transpose = false;
}
}
else if( IsCommentChar(sc.ch) && sc.chNext == '{' && nonSpaceColumn == column)
else if( IsCommentChar(sc.ch) && sc.chNext == '{' && nonSpaceColumn == column && IsSpaceToEOL(sc.currentPos+2, styler))
{
commentDepth ++;
@ -214,8 +233,11 @@ static void ColouriseMatlabOctaveDoc(
if (sc.state == SCE_MATLAB_DEFAULT) {
if (IsCommentChar(sc.ch)) {
// ncrement depth if we are a block comment
if(sc.chNext == '{' && nonSpaceColumn == column)
commentDepth ++;
if(sc.chNext == '{' && nonSpaceColumn == column) {
if(IsSpaceToEOL(sc.currentPos+2, styler)) {
commentDepth ++;
}
}
curLine = styler.GetLine(sc.currentPos);
styler.SetLineState(curLine, commentDepth);
sc.SetState(SCE_MATLAB_COMMENT);
@ -238,6 +260,12 @@ static void ColouriseMatlabOctaveDoc(
} else if (isalpha(sc.ch)) {
sc.SetState(SCE_MATLAB_KEYWORD);
} else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@' || sc.ch == '\\') {
if (sc.ch == '(' || sc.ch == '[' || sc.ch == '{') {
allow_end_op ++;
} else if ((sc.ch == ')' || sc.ch == ']' || sc.ch == '}') && (allow_end_op > 0)) {
allow_end_op --;
}
if (sc.ch == ')' || sc.ch == ']' || sc.ch == '}') {
transpose = true;
} else {
@ -266,6 +294,12 @@ static void FoldMatlabOctaveDoc(Sci_PositionU startPos, Sci_Position length, int
WordList *[], Accessor &styler,
bool (*IsComment)(int ch)) {
if (styler.GetPropertyInt("fold") == 0)
return;
const bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
Sci_PositionU endPos = startPos + length;
int visibleChars = 0;
Sci_Position lineCurrent = styler.GetLine(startPos);
@ -286,11 +320,11 @@ static void FoldMatlabOctaveDoc(Sci_PositionU startPos, Sci_Position length, int
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
// a line that starts with a comment
if (style == SCE_MATLAB_COMMENT && IsComment(ch) && visibleChars == 0) {
if (foldComment && style == SCE_MATLAB_COMMENT && IsComment(ch) && visibleChars == 0) {
// start/end of block comment
if (chNext == '{')
if (chNext == '{' && IsSpaceToEOL(i+2, styler))
levelNext ++;
if (chNext == '}')
if (chNext == '}' && IsSpaceToEOL(i+2, styler))
levelNext --;
}
// keyword
@ -305,14 +339,14 @@ static void FoldMatlabOctaveDoc(Sci_PositionU startPos, Sci_Position length, int
wordlen = 0;
levelNext += CheckKeywordFoldPoint(word);
}
}
}
if (!IsASpace(ch))
visibleChars++;
if (atEOL || (i == endPos-1)) {
int levelUse = levelCurrent;
int lev = levelUse | levelNext << 16;
if (visibleChars == 0)
if (visibleChars == 0 && foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG;
if (levelUse < levelNext)
lev |= SC_FOLDLEVELHEADERFLAG;

View file

@ -0,0 +1,222 @@
// Scintilla source code edit control
/** @file LexMaxima.cxx
** Lexer for Maxima (http://maxima.sourceforge.net).
** Written by Gunter Königsmann based on the lisp lexer by Alexey Yutkin and Neil Hodgson .
**/
// Copyright 2018 by Gunter Königsmann <wxMaxima@physikbuch.de>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
#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"
using namespace Scintilla;
static inline bool isMaximaoperator(char ch) {
return (ch == '\'' || ch == '`' || ch == '(' ||
ch == ')' || ch == '[' || ch == ']' ||
ch == '{' || ch == '}' || ch == '!' ||
ch == '*' || ch == '/' || ch == '^' ||
ch == ',' || ch == ':' || ch == '+' ||
ch == '-');
}
static void ColouriseMaximaDoc(Sci_PositionU startPos, Sci_Position length, int lastStyle,
WordList *[],
Accessor &styler) {
styler.StartAt(startPos);
Sci_PositionU lengthDoc = startPos + length;
styler.StartSegment(startPos);
Sci_PositionU i = startPos;
// If we are in the middle of a comment we go back to its start before highlighting
if(lastStyle == SCE_MAXIMA_COMMENT)
{
while((i>0) &&
!((styler.SafeGetCharAt(i+1) == '*') && (styler.SafeGetCharAt(i) == '/')))
i--;
}
for (; i < lengthDoc; i++) {
char ch = styler.SafeGetCharAt(i);
char chNext = styler.SafeGetCharAt(i + 1);
if (styler.IsLeadByte(ch))
continue;
// Handle comments.
// Comments start with /* and end with */
if((ch == '/') && (chNext == '*'))
{
i++;i++;
chNext = styler.SafeGetCharAt(i);
for (; i < lengthDoc; i++)
{
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
if((ch == '*') && (chNext == '/'))
{
i++;
i++;
break;
}
}
if(i > lengthDoc)
i = lengthDoc;
i--;
styler.ColourTo(i, SCE_MAXIMA_COMMENT);
continue;
}
// Handle Operators
if(isMaximaoperator(ch))
{
styler.ColourTo(i, SCE_MAXIMA_OPERATOR);
continue;
}
// Handle command endings.
if((ch == '$') || (ch == ';'))
{
styler.ColourTo(i, SCE_MAXIMA_COMMANDENDING);
continue;
}
// Handle numbers. Numbers always begin with a digit.
if(IsASCII(ch) && isdigit(ch))
{
i++;
for (; i < lengthDoc; i++)
{
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
if(ch == '.')
continue;
// A "e" or similar can be followed by a "+" or a "-"
if(((ch == 'e') || (ch == 'b') || (ch == 'g') || (ch == 'f')) &&
((chNext == '+') || (chNext == '-')))
{
i++;
chNext = styler.SafeGetCharAt(i + 1);
continue;
}
if(!IsASCII(ch) || !(isdigit(ch) || islower(ch) || isupper(ch)))
{
i--;
break;
}
}
styler.ColourTo(i, SCE_MAXIMA_NUMBER);
continue;
}
// Handle strings
if(ch == '\"')
{
i++;
for (; i < lengthDoc; i++)
{
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
if(ch == '\\')
i++;
else
{
if(ch == '\"')
break;
}
}
styler.ColourTo(i, SCE_MAXIMA_STRING);
continue;
}
// Handle keywords. Maxima treats Non-ASCII chars as ordinary letters.
if(((!IsASCII(ch))) || isalpha(ch) || (ch == '_'))
{
char cmd[100];
int cmdidx = 0;
memset(cmd,0,100);
cmd[cmdidx++] = ch;
i++;
for (; i < lengthDoc; i++)
{
ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
if(ch == '\\')
{
if(cmdidx < 99)
cmd[cmdidx++] = ch;
i++;
if(cmdidx < 99)
cmd[cmdidx++] = ch;
continue;
}
if(isMaximaoperator(ch) || ((IsASCII(ch) && !isalpha(ch) && !isdigit(ch) && (ch != '_'))))
{
i--;
break;
}
if(cmdidx < 99)
cmd[cmdidx++] = ch;
}
// A few known keywords
if(
(strncmp(cmd,"if",99) == 0) ||
(strncmp(cmd,"then",99) == 0) ||
(strncmp(cmd,"else",99) == 0) ||
(strncmp(cmd,"thru",99) == 0) ||
(strncmp(cmd,"for",99) == 0) ||
(strncmp(cmd,"while",99) == 0) ||
(strncmp(cmd,"do",99) == 0)
)
{
styler.ColourTo(i, SCE_MAXIMA_COMMAND);
continue;
}
// All other keywords are functions if they are followed
// by an opening parenthesis
char nextNonwhitespace = ' ';
for (Sci_PositionU o = i + 1; o < lengthDoc; o++)
{
nextNonwhitespace = styler.SafeGetCharAt(o);
if(!IsASCII(nextNonwhitespace) || !isspacechar(nextNonwhitespace))
break;
}
if(nextNonwhitespace == '(')
{
styler.ColourTo(i, SCE_MAXIMA_COMMAND);
}
else
{
styler.ColourTo(i, SCE_MAXIMA_VARIABLE);
}
continue;
}
styler.ColourTo(i-1, SCE_MAXIMA_UNKNOWN);
}
}
LexerModule lmMaxima(SCLEX_MAXIMA, ColouriseMaximaDoc, "maxima", 0, 0);

View file

@ -1,6 +1,6 @@
// Scintilla source code edit control
// File: LexMetapost.cxx - general context conformant metapost coloring scheme
// @file LexMetapost.cxx - general context conformant metapost coloring scheme
// Author: Hans Hagen - PRAGMA ADE - Hasselt NL - www.pragma-ade.com
// Version: September 28, 2003
// Modified by instanton: July 10, 2007
@ -30,9 +30,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
// val SCE_METAPOST_DEFAULT = 0
// val SCE_METAPOST_SPECIAL = 1
@ -179,7 +177,8 @@ static void ColouriseMETAPOSTDoc(
}
WordList &keywords = *keywordlists[0] ;
WordList &keywords2 = *keywordlists[extraInterface-1] ;
WordList kwEmpty;
WordList &keywords2 = (extraInterface > 0) ? *keywordlists[extraInterface - 1] : kwEmpty;
StyleContext sc(startPos, length, SCE_METAPOST_TEXT, styler) ;

View file

@ -28,13 +28,11 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
#ifdef DEBUG_LEX_MODULA
#define DEBUG_STATE( p, c )\
fprintf( stderr, "Unknown state: currentPos = %ud, char = '%c'\n", p, c );
fprintf( stderr, "Unknown state: currentPos = %u, char = '%c'\n", static_cast<unsigned int>(p), c );
#else
#define DEBUG_STATE( p, c )
#endif

View file

@ -28,9 +28,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsAWordChar(int ch) {
return (ch < 0x80) && (isalnum(ch) || ch == '_');
@ -55,7 +53,7 @@ static inline bool IsANumberChar(int ch) {
*/
static void CheckForKeyword(StyleContext& sc, WordList* keywordlists[], int activeState)
{
int length = sc.LengthCurrent() + 1; // +1 for the next char
Sci_Position length = sc.LengthCurrent() + 1; // +1 for the next char
char* s = new char[length];
sc.GetCurrentLowered(s, length);
if (keywordlists[0]->InList(s))

View file

@ -0,0 +1,811 @@
// Scintilla source code edit control
/** @file LexNim.cxx
** Lexer for Nim
** Written by Jad Altahan (github.com/xv)
** Nim manual: https://nim-lang.org/docs/manual.html
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
#include <string>
#include <map>
#include <algorithm>
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
#include "StringCopy.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;
namespace {
// Use an unnamed namespace to protect the functions and classes from name conflicts
enum NumType {
Binary,
Octal,
Exponent,
Hexadecimal,
Decimal,
FormatError
};
int GetNumStyle(const int numType) noexcept {
if (numType == NumType::FormatError) {
return SCE_NIM_NUMERROR;
}
return SCE_NIM_NUMBER;
}
constexpr bool IsLetter(const int ch) noexcept {
// 97 to 122 || 65 to 90
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z');
}
bool IsAWordChar(const int ch) noexcept {
return ch < 0x80 && (isalnum(ch) || ch == '_' || ch == '.');
}
int IsNumHex(const StyleContext &sc) noexcept {
return sc.chNext == 'x' || sc.chNext == 'X';
}
int IsNumBinary(const StyleContext &sc) noexcept {
return sc.chNext == 'b' || sc.chNext == 'B';
}
int IsNumOctal(const StyleContext &sc) {
return IsADigit(sc.chNext) || sc.chNext == 'o';
}
constexpr bool IsNewline(const int ch) noexcept {
return (ch == '\n' || ch == '\r');
}
bool IsFuncName(const char *str) noexcept {
const char *identifiers[] = {
"proc",
"func",
"macro",
"method",
"template",
"iterator",
"converter"
};
for (const char *id : identifiers) {
if (strcmp(str, id) == 0) {
return true;
}
}
return false;
}
constexpr bool IsTripleLiteral(const int style) noexcept {
return style == SCE_NIM_TRIPLE || style == SCE_NIM_TRIPLEDOUBLE;
}
constexpr bool IsLineComment(const int style) noexcept {
return style == SCE_NIM_COMMENTLINE || style == SCE_NIM_COMMENTLINEDOC;
}
constexpr bool IsStreamComment(const int style) noexcept {
return style == SCE_NIM_COMMENT || style == SCE_NIM_COMMENTDOC;
}
// Adopted from Accessor.cxx
int GetIndent(const Sci_Position line, Accessor &styler) {
Sci_Position startPos = styler.LineStart(line);
const Sci_Position eolPos = styler.LineStart(line + 1) - 1;
char ch = styler[startPos];
int style = styler.StyleAt(startPos);
int indent = 0;
bool inPrevPrefix = line > 0;
Sci_Position posPrev = inPrevPrefix ? styler.LineStart(line - 1) : 0;
// No fold points inside triple literals
while ((IsASpaceOrTab(ch) || IsTripleLiteral(style)) && (startPos < eolPos)) {
if (inPrevPrefix) {
const char chPrev = styler[posPrev++];
if (chPrev != ' ' && chPrev != '\t') {
inPrevPrefix = false;
}
}
if (ch == '\t') {
indent = (indent / 8 + 1) * 8;
} else {
indent++;
}
startPos++;
ch = styler[startPos];
style = styler.StyleAt(startPos);
}
// Prevent creating fold lines for comments if indented
if (!(IsStreamComment(style) || IsLineComment(style)))
indent += SC_FOLDLEVELBASE;
if (styler.LineStart(line) == styler.Length()
|| IsASpaceOrTab(ch)
|| IsNewline(ch)
|| IsStreamComment(style)
|| IsLineComment(style)) {
return indent | SC_FOLDLEVELWHITEFLAG;
} else {
return indent;
}
}
int IndentAmount(const Sci_Position line, Accessor &styler) {
const int indent = GetIndent(line, styler);
const int indentLevel = indent & SC_FOLDLEVELNUMBERMASK;
return indentLevel <= SC_FOLDLEVELBASE ? indent : indentLevel | (indent & ~SC_FOLDLEVELNUMBERMASK);
}
struct OptionsNim {
bool fold;
bool foldCompact;
bool highlightRawStrIdent;
OptionsNim() {
fold = true;
foldCompact = true;
highlightRawStrIdent = false;
}
};
static const char *const nimWordListDesc[] = {
"Keywords",
nullptr
};
struct OptionSetNim : public OptionSet<OptionsNim> {
OptionSetNim() {
DefineProperty("lexer.nim.raw.strings.highlight.ident", &OptionsNim::highlightRawStrIdent,
"Set to 1 to enable highlighting generalized raw string identifiers. "
"Generalized raw string identifiers are anything other than r (or R).");
DefineProperty("fold", &OptionsNim::fold);
DefineProperty("fold.compact", &OptionsNim::foldCompact);
DefineWordListSets(nimWordListDesc);
}
};
LexicalClass lexicalClasses[] = {
// Lexer Nim SCLEX_NIM SCE_NIM_:
0, "SCE_NIM_DEFAULT", "default", "White space",
1, "SCE_NIM_COMMENT", "comment block", "Block comment",
2, "SCE_NIM_COMMENTDOC", "comment block doc", "Block doc comment",
3, "SCE_NIM_COMMENTLINE", "comment line", "Line comment",
4, "SCE_NIM_COMMENTLINEDOC", "comment doc", "Line doc comment",
5, "SCE_NIM_NUMBER", "literal numeric", "Number",
6, "SCE_NIM_STRING", "literal string", "String",
7, "SCE_NIM_CHARACTER", "literal string", "Single quoted string",
8, "SCE_NIM_WORD", "keyword", "Keyword",
9, "SCE_NIM_TRIPLE", "literal string", "Triple quotes",
10, "SCE_NIM_TRIPLEDOUBLE", "literal string", "Triple double quotes",
11, "SCE_NIM_BACKTICKS", "operator definition", "Identifiers",
12, "SCE_NIM_FUNCNAME", "identifier", "Function name definition",
13, "SCE_NIM_STRINGEOL", "error literal string", "String is not closed",
14, "SCE_NIM_NUMERROR", "numeric error", "Numeric format error",
15, "SCE_NIM_OPERATOR", "operator", "Operators",
16, "SCE_NIM_IDENTIFIER", "identifier", "Identifiers",
};
}
class LexerNim : public DefaultLexer {
CharacterSet setWord;
WordList keywords;
OptionsNim options;
OptionSetNim osNim;
public:
LexerNim() :
DefaultLexer("nim", SCLEX_NIM, lexicalClasses, ELEMENTS(lexicalClasses)),
setWord(CharacterSet::setAlphaNum, "_", 0x80, true) { }
virtual ~LexerNim() { }
void SCI_METHOD Release() noexcept override {
delete this;
}
int SCI_METHOD Version() const noexcept override {
return lvIdentity;
}
const char * SCI_METHOD PropertyNames() override {
return osNim.PropertyNames();
}
int SCI_METHOD PropertyType(const char *name) override {
return osNim.PropertyType(name);
}
const char * SCI_METHOD DescribeProperty(const char *name) override {
return osNim.DescribeProperty(name);
}
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
const char * SCI_METHOD PropertyGet(const char* key) override {
return osNim.PropertyGet(key);
}
const char * SCI_METHOD DescribeWordListSets() override {
return osNim.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 *) noexcept override {
return nullptr;
}
int SCI_METHOD LineEndTypesSupported() noexcept override {
return SC_LINE_END_TYPE_UNICODE;
}
int SCI_METHOD PrimaryStyleFromStyle(int style) noexcept override {
return style;
}
static ILexer *LexerFactoryNim() {
return new LexerNim();
}
};
Sci_Position SCI_METHOD LexerNim::PropertySet(const char *key, const char *val) {
if (osNim.PropertySet(&options, key, val)) {
return 0;
}
return -1;
}
Sci_Position SCI_METHOD LexerNim::WordListSet(int n, const char *wl) {
WordList *wordListN = nullptr;
switch (n) {
case 0:
wordListN = &keywords;
break;
}
Sci_Position firstModification = -1;
if (wordListN) {
WordList wlNew;
wlNew.Set(wl);
if (*wordListN != wlNew) {
wordListN->Set(wl);
firstModification = 0;
}
}
return firstModification;
}
void SCI_METHOD LexerNim::Lex(Sci_PositionU startPos, Sci_Position length,
int initStyle, IDocument *pAccess) {
// No one likes a leaky string
if (initStyle == SCE_NIM_STRINGEOL) {
initStyle = SCE_NIM_DEFAULT;
}
Accessor styler(pAccess, nullptr);
StyleContext sc(startPos, length, initStyle, styler);
// Nim supports nested block comments!
Sci_Position lineCurrent = styler.GetLine(startPos);
int commentNestLevel = lineCurrent > 0 ? styler.GetLineState(lineCurrent - 1) : 0;
int numType = NumType::Decimal;
int decimalCount = 0;
bool funcNameExists = false;
bool isStylingRawString = false;
bool isStylingRawStringIdent = false;
for (; sc.More(); sc.Forward()) {
if (sc.atLineStart) {
if (sc.state == SCE_NIM_STRING) {
sc.SetState(SCE_NIM_STRING);
}
lineCurrent = styler.GetLine(sc.currentPos);
styler.SetLineState(lineCurrent, commentNestLevel);
}
// Handle string line continuation
if (sc.ch == '\\' && (sc.chNext == '\n' || sc.chNext == '\r') &&
(sc.state == SCE_NIM_STRING || sc.state == SCE_NIM_CHARACTER) && !isStylingRawString) {
sc.Forward();
if (sc.ch == '\r' && sc.chNext == '\n') {
sc.Forward();
}
continue;
}
switch (sc.state) {
case SCE_NIM_OPERATOR:
funcNameExists = false;
sc.SetState(SCE_NIM_DEFAULT);
break;
case SCE_NIM_NUMBER:
// For a type suffix, such as 0x80'u8
if (sc.ch == '\'') {
if (sc.chNext == 'i' || sc.chNext == 'I' ||
sc.chNext == 'u' || sc.chNext == 'U' ||
sc.chNext == 'f' || sc.chNext == 'F' ||
sc.chNext == 'd' || sc.chNext == 'D') {
sc.Forward(2);
}
} else if (sc.ch == '.') {
if (IsADigit(sc.chNext)) {
sc.Forward();
} else if (numType <= NumType::Exponent) {
sc.SetState(SCE_NIM_OPERATOR);
break;
} else {
decimalCount++;
if (numType == NumType::Decimal) {
if (decimalCount <= 1 && !IsAWordChar(sc.chNext)) {
break;
}
} else if (numType == NumType::Hexadecimal) {
if (decimalCount <= 1 && IsADigit(sc.chNext, 16)) {
break;
}
sc.SetState(SCE_NIM_OPERATOR);
break;
}
}
} else if (sc.ch == '_') {
// Accept only one underscore between digits
if (IsADigit(sc.chNext)) {
sc.Forward();
}
} else if (numType == NumType::Decimal) {
if (sc.chPrev != '\'' && (sc.ch == 'e' || sc.ch == 'E')) {
numType = NumType::Exponent;
if (sc.chNext == '-' || sc.chNext == '+') {
sc.Forward();
}
break;
}
if (IsADigit(sc.ch)) {
break;
}
} else if (numType == NumType::Hexadecimal) {
if (IsADigit(sc.ch, 16)) {
break;
}
} else if (IsADigit(sc.ch)) {
if (numType == NumType::Exponent) {
break;
}
if (numType == NumType::Octal) {
// Accept only 0-7
if (sc.ch <= '7') {
break;
}
} else if (numType == NumType::Binary) {
// Accept only 0 and 1
if (sc.ch <= '1') {
break;
}
}
numType = NumType::FormatError;
break;
}
sc.ChangeState(GetNumStyle(numType));
sc.SetState(SCE_NIM_DEFAULT);
break;
case SCE_NIM_IDENTIFIER:
if (sc.ch == '.' || !IsAWordChar(sc.ch)) {
char s[100];
sc.GetCurrent(s, sizeof(s));
int style = SCE_NIM_IDENTIFIER;
if (keywords.InList(s) && !funcNameExists) {
// Prevent styling keywords if they are sub-identifiers
const Sci_Position segStart = styler.GetStartSegment() - 1;
if (segStart < 0 || styler.SafeGetCharAt(segStart, '\0') != '.') {
style = SCE_NIM_WORD;
}
} else if (funcNameExists) {
style = SCE_NIM_FUNCNAME;
}
sc.ChangeState(style);
sc.SetState(SCE_NIM_DEFAULT);
if (style == SCE_NIM_WORD) {
funcNameExists = IsFuncName(s);
} else {
funcNameExists = false;
}
}
if (IsAlphaNumeric(sc.ch) && sc.chNext == '\"') {
isStylingRawStringIdent = true;
if (options.highlightRawStrIdent) {
if (styler.SafeGetCharAt(sc.currentPos + 2) == '\"' &&
styler.SafeGetCharAt(sc.currentPos + 3) == '\"') {
sc.ChangeState(SCE_NIM_TRIPLEDOUBLE);
} else {
sc.ChangeState(SCE_NIM_STRING);
}
}
sc.ForwardSetState(SCE_NIM_DEFAULT);
}
break;
case SCE_NIM_FUNCNAME:
if (sc.ch == '`') {
funcNameExists = false;
sc.ForwardSetState(SCE_NIM_DEFAULT);
} else if (sc.atLineEnd) {
// Prevent leaking the style to the next line if not closed
funcNameExists = false;
sc.ChangeState(SCE_NIM_STRINGEOL);
sc.ForwardSetState(SCE_NIM_DEFAULT);
}
break;
case SCE_NIM_COMMENT:
if (sc.Match(']', '#')) {
if (commentNestLevel > 0) {
commentNestLevel--;
}
lineCurrent = styler.GetLine(sc.currentPos);
styler.SetLineState(lineCurrent, commentNestLevel);
sc.Forward();
if (commentNestLevel == 0) {
sc.ForwardSetState(SCE_NIM_DEFAULT);
}
} else if (sc.Match('#', '[')) {
commentNestLevel++;
lineCurrent = styler.GetLine(sc.currentPos);
styler.SetLineState(lineCurrent, commentNestLevel);
}
break;
case SCE_NIM_COMMENTDOC:
if (sc.Match("]##")) {
if (commentNestLevel > 0) {
commentNestLevel--;
}
lineCurrent = styler.GetLine(sc.currentPos);
styler.SetLineState(lineCurrent, commentNestLevel);
sc.Forward(2);
if (commentNestLevel == 0) {
sc.ForwardSetState(SCE_NIM_DEFAULT);
}
} else if (sc.Match("##[")) {
commentNestLevel++;
lineCurrent = styler.GetLine(sc.currentPos);
styler.SetLineState(lineCurrent, commentNestLevel);
}
break;
case SCE_NIM_COMMENTLINE:
case SCE_NIM_COMMENTLINEDOC:
if (sc.atLineStart) {
sc.SetState(SCE_NIM_DEFAULT);
}
break;
case SCE_NIM_STRING:
if (!isStylingRawStringIdent && !isStylingRawString && sc.ch == '\\') {
if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
sc.Forward();
}
} else if (isStylingRawString && sc.ch == '\"' && sc.chNext == '\"') {
// Forward in situations such as r"a""bc\" so that "bc\" wouldn't be
// considered a string of its own
sc.Forward();
} else if (sc.ch == '\"') {
sc.ForwardSetState(SCE_NIM_DEFAULT);
} else if (sc.atLineEnd) {
sc.ChangeState(SCE_NIM_STRINGEOL);
sc.ForwardSetState(SCE_NIM_DEFAULT);
}
break;
case SCE_NIM_CHARACTER:
if (sc.ch == '\\') {
if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
sc.Forward();
}
} else if (sc.ch == '\'') {
sc.ForwardSetState(SCE_NIM_DEFAULT);
} else if (sc.atLineEnd) {
sc.ChangeState(SCE_NIM_STRINGEOL);
sc.ForwardSetState(SCE_NIM_DEFAULT);
}
break;
case SCE_NIM_BACKTICKS:
if (sc.ch == '`' ) {
sc.ForwardSetState(SCE_NIM_DEFAULT);
} else if (sc.atLineEnd) {
sc.ChangeState(SCE_NIM_STRINGEOL);
sc.ForwardSetState(SCE_NIM_DEFAULT);
}
break;
case SCE_NIM_TRIPLEDOUBLE:
if (sc.Match(R"(""")")) {
// Outright forward all " after the closing """ as a triple double
//
// A valid example where this is needed is: """8 double quotes->""""""""
// You can have as many """ at the end as you wish, as long as the actual
// closing literal is there
while (sc.ch == '"') {
sc.Forward();
}
sc.SetState(SCE_NIM_DEFAULT);
}
break;
case SCE_NIM_TRIPLE:
if (sc.Match("'''")) {
sc.Forward(2);
sc.ForwardSetState(SCE_NIM_DEFAULT);
}
break;
}
if (sc.state == SCE_NIM_DEFAULT) {
// Number
if (IsADigit(sc.ch)) {
sc.SetState(SCE_NIM_NUMBER);
numType = NumType::Decimal;
decimalCount = 0;
if (sc.ch == '0') {
if (IsNumHex(sc)) {
numType = NumType::Hexadecimal;
} else if (IsNumBinary(sc)) {
numType = NumType::Binary;
} else if (IsNumOctal(sc)) {
numType = NumType::Octal;
}
if (numType != NumType::Decimal) {
sc.Forward();
}
}
}
// Raw string
else if (IsAlphaNumeric(sc.ch) && sc.chNext == '\"') {
isStylingRawString = true;
// Triple doubles can be raw strings too. How sweet
if (styler.SafeGetCharAt(sc.currentPos + 2) == '\"' &&
styler.SafeGetCharAt(sc.currentPos + 3) == '\"') {
sc.SetState(SCE_NIM_TRIPLEDOUBLE);
} else {
sc.SetState(SCE_NIM_STRING);
}
const int rawStrStyle = options.highlightRawStrIdent ? IsLetter(sc.ch) :
(sc.ch == 'r' || sc.ch == 'R');
if (rawStrStyle) {
sc.Forward();
if (sc.state == SCE_NIM_TRIPLEDOUBLE) {
sc.Forward(2);
}
} else {
// Anything other than r/R is considered a general raw string identifier
isStylingRawStringIdent = true;
sc.SetState(SCE_NIM_IDENTIFIER);
}
}
// String and triple double literal
else if (sc.ch == '\"') {
isStylingRawString = false;
if (sc.Match(R"(""")")) {
sc.SetState(SCE_NIM_TRIPLEDOUBLE);
// Keep forwarding until the total opening literal count is 5
// A valid example where this is needed is: """""<-5 double quotes"""
while (sc.ch == '"') {
sc.Forward();
if (sc.Match(R"(""")")) {
sc.Forward();
break;
}
}
} else {
sc.SetState(SCE_NIM_STRING);
}
}
// Charecter and triple literal
else if (sc.ch == '\'') {
if (sc.Match("'''")) {
sc.SetState(SCE_NIM_TRIPLE);
} else {
sc.SetState(SCE_NIM_CHARACTER);
}
}
// Operator definition
else if (sc.ch == '`') {
if (funcNameExists) {
sc.SetState(SCE_NIM_FUNCNAME);
} else {
sc.SetState(SCE_NIM_BACKTICKS);
}
}
// Keyword
else if (iswordstart(sc.ch)) {
sc.SetState(SCE_NIM_IDENTIFIER);
}
// Comments
else if (sc.ch == '#') {
if (sc.Match("##[") || sc.Match("#[")) {
commentNestLevel++;
lineCurrent = styler.GetLine(sc.currentPos);
styler.SetLineState(lineCurrent, commentNestLevel);
}
if (sc.Match("##[")) {
sc.SetState(SCE_NIM_COMMENTDOC);
sc.Forward();
} else if (sc.Match("#[")) {
sc.SetState(SCE_NIM_COMMENT);
sc.Forward();
} else if (sc.Match("##")) {
sc.SetState(SCE_NIM_COMMENTLINEDOC);
} else {
sc.SetState(SCE_NIM_COMMENTLINE);
}
}
// Operators
else if (strchr("()[]{}:=;-\\/&%$!+<>|^?,.*~@", sc.ch)) {
sc.SetState(SCE_NIM_OPERATOR);
}
}
if (sc.atLineEnd) {
funcNameExists = false;
isStylingRawString = false;
isStylingRawStringIdent = false;
}
}
sc.Complete();
}
void SCI_METHOD LexerNim::Fold(Sci_PositionU startPos, Sci_Position length, int, IDocument *pAccess) {
if (!options.fold) {
return;
}
Accessor styler(pAccess, nullptr);
const Sci_Position docLines = styler.GetLine(styler.Length());
const Sci_Position maxPos = startPos + length;
const Sci_Position maxLines = styler.GetLine(maxPos == styler.Length() ? maxPos : maxPos - 1);
Sci_Position lineCurrent = styler.GetLine(startPos);
int indentCurrent = IndentAmount(lineCurrent, styler);
while (lineCurrent > 0) {
lineCurrent--;
indentCurrent = IndentAmount(lineCurrent, styler);
if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
break;
}
}
int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
indentCurrent = indentCurrentLevel | (indentCurrent & ~SC_FOLDLEVELNUMBERMASK);
while (lineCurrent <= docLines && lineCurrent <= maxLines) {
Sci_Position lineNext = lineCurrent + 1;
int indentNext = indentCurrent;
int lev = indentCurrent;
if (lineNext <= docLines) {
indentNext = IndentAmount(lineNext, styler);
}
if (indentNext & SC_FOLDLEVELWHITEFLAG) {
indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel;
}
while (lineNext < docLines && (indentNext & SC_FOLDLEVELWHITEFLAG)) {
lineNext++;
indentNext = IndentAmount(lineNext, styler);
}
const int indentNextLevel = indentNext & SC_FOLDLEVELNUMBERMASK;
indentNext = indentNextLevel | (indentNext & ~SC_FOLDLEVELNUMBERMASK);
const int levelBeforeComments = std::max(indentCurrentLevel, indentNextLevel);
Sci_Position skipLine = lineNext;
int skipLevel = indentNextLevel;
while (--skipLine > lineCurrent) {
const int skipLineIndent = IndentAmount(skipLine, styler);
if (options.foldCompact) {
if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > indentNextLevel) {
skipLevel = levelBeforeComments;
}
const int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG;
styler.SetLevel(skipLine, skipLevel | whiteFlag);
} else {
if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > indentNextLevel &&
!(skipLineIndent & SC_FOLDLEVELWHITEFLAG)) {
skipLevel = levelBeforeComments;
}
styler.SetLevel(skipLine, skipLevel);
}
}
if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
lev |= SC_FOLDLEVELHEADERFLAG;
}
}
styler.SetLevel(lineCurrent, options.foldCompact ? lev : lev & ~SC_FOLDLEVELWHITEFLAG);
indentCurrent = indentNext;
indentCurrentLevel = indentNextLevel;
lineCurrent = lineNext;
}
}
LexerModule lmNim(SCLEX_NIM, LexerNim::LexerFactoryNim, "nim", nimWordListDesc);

View file

@ -25,9 +25,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsAWordChar(int ch) {
return (ch >= 0x80) || isalnum(ch) || ch == '_';

View file

@ -24,9 +24,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
/*
// located in SciLexer.h

View file

@ -23,9 +23,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static void ColouriseNullDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[],
Accessor &styler) {

View file

@ -26,9 +26,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
// -----------------------------------------
// Functions classifying a single character.
@ -464,7 +462,7 @@ static void FoldOScriptDoc(Sci_PositionU startPos, Sci_Position length, int init
char chNext = styler[startPos];
int styleNext = styler.StyleAt(startPos);
int style = initStyle;
int lastStart = 0;
Sci_Position lastStart = 0;
for (Sci_Position i = startPos; i < endPos; i++) {
char ch = chNext;

View file

@ -22,9 +22,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
inline static void getRange( Sci_PositionU start, Sci_PositionU end, Accessor & styler, char * s, Sci_PositionU len )
{

View file

@ -51,9 +51,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsTypeCharacter(const int ch)
{

View file

@ -1,4 +1,5 @@
// Copyright (c) 1990-2007, Scientific Toolworks, Inc.
// @file LexPLM.cxx
// Author: Jason Haslam
// The License.txt file describes the conditions under which this software may be distributed.
@ -20,9 +21,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static void GetRange(Sci_PositionU start,
Sci_PositionU end,

View file

@ -31,9 +31,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static void ColourisePODoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *[], Accessor &styler) {
StyleContext sc(startPos, length, initStyle, styler);

View file

@ -32,9 +32,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsAWordChar(int ch) {
return ch < 0x80 && (isalnum(ch) || ch == '_');

View file

@ -30,9 +30,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsASelfDelimitingChar(const int ch) {
return (ch == '[' || ch == ']' || ch == '{' || ch == '}' ||

View file

@ -128,9 +128,7 @@ contains requires
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static void GetRangeLowered(Sci_PositionU start,
Sci_PositionU end,

View file

@ -27,10 +27,9 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"
#include "DefaultLexer.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
// Info for HERE document handling from perldata.pod (reformatted):
// ----------------------------------------------------------------
@ -38,6 +37,8 @@ using namespace Scintilla;
// Following a << you specify a string to terminate the quoted material, and
// all lines following the current line down to the terminating string are
// the value of the item.
// Prefixing the terminating string with a "~" specifies that you want to
// use "Indented Here-docs" (see below).
// * The terminating string may be either an identifier (a word), or some
// quoted text.
// * If quoted, the type of quotes you use determines the treatment of the
@ -49,6 +50,18 @@ using namespace Scintilla;
// (This is deprecated, -w warns of this syntax)
// * The terminating string must appear by itself (unquoted and
// with no surrounding whitespace) on the terminating line.
//
// Indented Here-docs
// ------------------
// The here-doc modifier "~" allows you to indent your here-docs to
// make the code more readable.
// The delimiter is used to determine the exact whitespace to remove
// from the beginning of each line. All lines must have at least the
// same starting whitespace (except lines only containing a newline)
// or perl will croak. Tabs and spaces can be mixed, but are matched
// exactly. One tab will not be equal to 8 spaces!
// Additional beginning whitespace (beyond what preceded the
// delimiter) will be preserved.
#define HERE_DELIM_MAX 256 // maximum length of HERE doc delimiter
@ -122,8 +135,8 @@ static int disambiguateBareword(LexAccessor &styler, Sci_PositionU bk, Sci_Posit
// if ch isn't one of '[{(,' we can skip the test
if ((ch == '{' || ch == '(' || ch == '['|| ch == ',')
&& fw < endPos) {
while (ch = static_cast<unsigned char>(styler.SafeGetCharAt(fw)),
IsASpaceOrTab(ch) && fw < endPos) {
while (IsASpaceOrTab(ch = static_cast<unsigned char>(styler.SafeGetCharAt(fw)))
&& fw < endPos) {
fw++;
}
if ((ch == '}' && brace)
@ -138,10 +151,12 @@ static int disambiguateBareword(LexAccessor &styler, Sci_PositionU bk, Sci_Posit
static void skipWhitespaceComment(LexAccessor &styler, Sci_PositionU &p) {
// when backtracking, we need to skip whitespace and comments
int style;
while ((p > 0) && (style = styler.StyleAt(p),
style == SCE_PL_DEFAULT || style == SCE_PL_COMMENTLINE))
while (p > 0) {
const int style = styler.StyleAt(p);
if (style != SCE_PL_DEFAULT && style != SCE_PL_COMMENTLINE)
break;
p--;
}
}
static int findPrevLexeme(LexAccessor &styler, Sci_PositionU &bk, int &style) {
@ -398,7 +413,7 @@ struct OptionSetPerl : public OptionSet<OptionsPerl> {
}
};
class LexerPerl : public ILexer {
class LexerPerl : public DefaultLexer {
CharacterSet setWordStart;
CharacterSet setWord;
CharacterSet setSpecialVar;
@ -408,6 +423,7 @@ class LexerPerl : public ILexer {
OptionSetPerl osPerl;
public:
LexerPerl() :
DefaultLexer("perl", SCLEX_PERL),
setWordStart(CharacterSet::setAlpha, "_", 0x80, true),
setWord(CharacterSet::setAlphaNum, "_", 0x80, true),
setSpecialVar(CharacterSet::setNone, "\"$;<>&`'+,./\\%:=~!?@[]"),
@ -415,30 +431,33 @@ public:
}
virtual ~LexerPerl() {
}
void SCI_METHOD Release() {
void SCI_METHOD Release() override {
delete this;
}
int SCI_METHOD Version() const {
return lvOriginal;
int SCI_METHOD Version() const override {
return lvIdentity;
}
const char *SCI_METHOD PropertyNames() {
const char *SCI_METHOD PropertyNames() override {
return osPerl.PropertyNames();
}
int SCI_METHOD PropertyType(const char *name) {
int SCI_METHOD PropertyType(const char *name) override {
return osPerl.PropertyType(name);
}
const char *SCI_METHOD DescribeProperty(const char *name) {
const char *SCI_METHOD DescribeProperty(const char *name) override {
return osPerl.DescribeProperty(name);
}
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val);
const char *SCI_METHOD DescribeWordListSets() {
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
const char * SCI_METHOD PropertyGet(const char *key) override {
return osPerl.PropertyGet(key);
}
const char *SCI_METHOD DescribeWordListSets() override {
return osPerl.DescribeWordListSets();
}
Sci_Position SCI_METHOD WordListSet(int n, const char *wl);
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess);
void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess);
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 *) {
void *SCI_METHOD PrivateCall(int, void *) override {
return 0;
}
@ -618,12 +637,14 @@ void SCI_METHOD LexerPerl::Lex(Sci_PositionU startPos, Sci_Position length, int
// 2: here doc text (lines after the delimiter)
int Quote; // the char after '<<'
bool Quoted; // true if Quote in ('\'','"','`')
bool StripIndent; // true if '<<~' requested to strip leading whitespace
int DelimiterLength; // strlen(Delimiter)
char Delimiter[HERE_DELIM_MAX]; // the Delimiter
HereDocCls() {
State = 0;
Quote = 0;
Quoted = false;
StripIndent = false;
DelimiterLength = 0;
Delimiter[0] = '\0';
}
@ -884,7 +905,7 @@ void SCI_METHOD LexerPerl::Lex(Sci_PositionU startPos, Sci_Position length, int
sc.SetState(SCE_PL_DEFAULT);
break;
case SCE_PL_COMMENTLINE:
if (sc.atLineEnd) {
if (sc.atLineStart) {
sc.SetState(SCE_PL_DEFAULT);
}
break;
@ -895,8 +916,14 @@ void SCI_METHOD LexerPerl::Lex(Sci_PositionU startPos, Sci_Position length, int
HereDoc.State = 1; // pre-init HERE doc class
HereDoc.Quote = sc.chNext;
HereDoc.Quoted = false;
HereDoc.StripIndent = false;
HereDoc.DelimiterLength = 0;
HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
if (delim_ch == '~') { // was actually '<<~'
sc.Forward();
HereDoc.StripIndent = true;
HereDoc.Quote = delim_ch = sc.chNext;
}
if (IsASpaceOrTab(delim_ch)) {
// skip whitespace; legal only for quoted delimiters
Sci_PositionU i = sc.currentPos + 1;
@ -963,6 +990,11 @@ void SCI_METHOD LexerPerl::Lex(Sci_PositionU startPos, Sci_Position length, int
case SCE_PL_HERE_QX:
// also implies HereDoc.State == 2
sc.Complete();
if (HereDoc.StripIndent) {
// skip whitespace
while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd)
sc.Forward();
}
if (HereDoc.DelimiterLength == 0 || sc.Match(HereDoc.Delimiter)) {
int c = sc.GetRelative(HereDoc.DelimiterLength);
if (c == '\r' || c == '\n') { // peek first, do not consume match
@ -1174,6 +1206,7 @@ void SCI_METHOD LexerPerl::Lex(Sci_PositionU startPos, Sci_Position length, int
break;
}
// (continued for ' delim)
// Falls through.
default: // non-interpolated path
sc.Forward(sLen);
}
@ -1699,6 +1732,12 @@ void SCI_METHOD LexerPerl::Fold(Sci_PositionU startPos, Sci_Position length, int
} else if (ch == ']') {
levelCurrent--;
}
} else if (style == SCE_PL_STRING_QW) {
// qw
if (stylePrevCh != style)
levelCurrent++;
else if (styleNext != style)
levelCurrent--;
}
// POD folding
if (options.foldPOD && atLineStart) {

View file

@ -43,9 +43,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsStreamCommentStyle(int style) {
return style == SCE_POWERPRO_COMMENTBLOCK;

View file

@ -23,9 +23,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
// Extended to accept accented characters
static inline bool IsAWordChar(int ch) {
@ -33,7 +31,7 @@ static inline bool IsAWordChar(int ch) {
}
static void ColourisePowerShellDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
WordList *keywordlists[], Accessor &styler) {
WordList *keywordlists[], Accessor &styler) {
WordList &keywords = *keywordlists[0];
WordList &keywords2 = *keywordlists[1];
@ -53,8 +51,8 @@ static void ColourisePowerShellDoc(Sci_PositionU startPos, Sci_Position length,
sc.SetState(SCE_POWERSHELL_DEFAULT);
}
} else if (sc.state == SCE_POWERSHELL_COMMENTSTREAM) {
if(sc.atLineStart) {
while(IsASpaceOrTab(sc.ch)) {
if (sc.atLineStart) {
while (IsASpaceOrTab(sc.ch)) {
sc.Forward();
}
if (sc.ch == '.' && IsAWordChar(sc.chNext)) {
@ -65,7 +63,7 @@ static void ColourisePowerShellDoc(Sci_PositionU startPos, Sci_Position length,
sc.ForwardSetState(SCE_POWERSHELL_DEFAULT);
}
} else if (sc.state == SCE_POWERSHELL_COMMENTDOCKEYWORD) {
if(!IsAWordChar(sc.ch)) {
if (!IsAWordChar(sc.ch)) {
char s[100];
sc.GetCurrentLowered(s, sizeof(s));
if (!keywords6.InList(s + 1)) {
@ -77,11 +75,15 @@ static void ColourisePowerShellDoc(Sci_PositionU startPos, Sci_Position length,
// This is a doubles quotes string
if (sc.ch == '\"') {
sc.ForwardSetState(SCE_POWERSHELL_DEFAULT);
} else if (sc.ch == '`') {
sc.Forward(); // skip next escaped character
}
} else if (sc.state == SCE_POWERSHELL_CHARACTER) {
// This is a single quote string
if (sc.ch == '\'') {
sc.ForwardSetState(SCE_POWERSHELL_DEFAULT);
} else if (sc.ch == '`') {
sc.Forward(); // skip next escaped character
}
} else if (sc.state == SCE_POWERSHELL_HERE_STRING) {
// This is a doubles quotes here-string
@ -161,7 +163,7 @@ static void ColourisePowerShellDoc(Sci_PositionU startPos, Sci_Position length,
// level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "} else {".
static void FoldPowerShellDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
WordList *[], Accessor &styler) {
WordList *[], Accessor &styler) {
bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
@ -236,7 +238,7 @@ static void FoldPowerShellDoc(Sci_PositionU startPos, Sci_Position length, int i
}
}
static const char * const powershellWordLists[] = {
static const char *const powershellWordLists[] = {
"Commands",
"Cmdlets",
"Aliases",

View file

@ -38,10 +38,9 @@ Differentiate between labels and variables
#include "LexerModule.h"
#include "OptionSet.h"
#include "SparseState.h"
#include "DefaultLexer.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
namespace {
// Use an unnamed namespace to protect the functions and classes from name conflicts
@ -122,7 +121,7 @@ namespace {
};
}
class LexerABL : public ILexer {
class LexerABL : public DefaultLexer {
CharacterSet setWord;
CharacterSet setNegationOp;
CharacterSet setArithmethicOp;
@ -137,6 +136,7 @@ class LexerABL : public ILexer {
OptionSetABL osABL;
public:
LexerABL() :
DefaultLexer("abl", SCLEX_PROGRESS),
setWord(CharacterSet::setAlphaNum, "_", 0x80, true),
setNegationOp(CharacterSet::setNone, "!"),
setArithmethicOp(CharacterSet::setNone, "+-/*%"),
@ -145,34 +145,37 @@ public:
}
virtual ~LexerABL() {
}
void SCI_METHOD Release() {
void SCI_METHOD Release() override {
delete this;
}
int SCI_METHOD Version() const {
return lvOriginal;
int SCI_METHOD Version() const override {
return lvIdentity;
}
const char * SCI_METHOD PropertyNames() {
const char * SCI_METHOD PropertyNames() override {
return osABL.PropertyNames();
}
int SCI_METHOD PropertyType(const char *name) {
int SCI_METHOD PropertyType(const char *name) override {
return osABL.PropertyType(name);
}
const char * SCI_METHOD DescribeProperty(const char *name) {
const char * SCI_METHOD DescribeProperty(const char *name) override {
return osABL.DescribeProperty(name);
}
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) ;
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override ;
const char * SCI_METHOD PropertyGet(const char *key) override {
return osABL.PropertyGet(key);
}
const char * SCI_METHOD DescribeWordListSets() {
const char * SCI_METHOD DescribeWordListSets() override {
return osABL.DescribeWordListSets();
}
Sci_Position SCI_METHOD WordListSet(int n, const char *wl);
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess);
void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess);
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 *) {
void * SCI_METHOD PrivateCall(int, void *) override {
return 0;
}
int SCI_METHOD LineEndTypesSupported() {
int SCI_METHOD LineEndTypesSupported() override {
return SC_LINE_END_TYPE_DEFAULT;
}
static ILexer *LexerFactoryABL() {
@ -278,10 +281,15 @@ void SCI_METHOD LexerABL::Lex(Sci_PositionU startPos, Sci_Position length, int i
// commentNestingLevel is a non-visible state, used to identify the nesting level of a comment
if (checkCommentNestingLevel) {
if (chPrev == '/' && ch == '*')
if (chPrev == '/' && ch == '*') {
commentNestingLevel++;
// eat the '/' so we don't miscount a */ if we see /*/*
--back;
}
if (chPrev == '*' && ch == '/') {
commentNestingLevel--;
// eat the '*' so we don't miscount a /* if we see */*/
--back;
}
}
--back;

View file

@ -12,6 +12,8 @@
#include <assert.h>
#include <ctype.h>
#include <string>
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
@ -23,9 +25,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool AtEOL(Accessor &styler, Sci_PositionU i) {
return (styler[i] == '\n') ||
@ -37,7 +37,7 @@ static inline bool isassignchar(unsigned char ch) {
}
static void ColourisePropsLine(
char *lineBuffer,
const char *lineBuffer,
Sci_PositionU lengthLine,
Sci_PositionU startLine,
Sci_PositionU endPos,
@ -81,39 +81,37 @@ static void ColourisePropsLine(
}
static void ColourisePropsDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) {
char lineBuffer[1024];
std::string lineBuffer;
styler.StartAt(startPos);
styler.StartSegment(startPos);
Sci_PositionU linePos = 0;
Sci_PositionU startLine = startPos;
// property lexer.props.allow.initial.spaces
// For properties files, set to 0 to style all lines that start with whitespace in the default style.
// This is not suitable for SciTE .properties files which use indentation for flow control but
// can be used for RFC2822 text where indentation is used for continuation lines.
bool allowInitialSpaces = styler.GetPropertyInt("lexer.props.allow.initial.spaces", 1) != 0;
const bool allowInitialSpaces = styler.GetPropertyInt("lexer.props.allow.initial.spaces", 1) != 0;
for (Sci_PositionU i = startPos; i < startPos + length; i++) {
lineBuffer[linePos++] = styler[i];
if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) {
lineBuffer.push_back(styler[i]);
if (AtEOL(styler, i)) {
// End of line (or of line buffer) met, colourise it
lineBuffer[linePos] = '\0';
ColourisePropsLine(lineBuffer, linePos, startLine, i, styler, allowInitialSpaces);
linePos = 0;
ColourisePropsLine(lineBuffer.c_str(), lineBuffer.length(), startLine, i, styler, allowInitialSpaces);
lineBuffer.clear();
startLine = i + 1;
}
}
if (linePos > 0) { // Last line does not have ending characters
ColourisePropsLine(lineBuffer, linePos, startLine, startPos + length - 1, styler, allowInitialSpaces);
if (lineBuffer.length() > 0) { // Last line does not have ending characters
ColourisePropsLine(lineBuffer.c_str(), lineBuffer.length(), startLine, startPos + length - 1, styler, allowInitialSpaces);
}
}
// adaption by ksc, using the "} else {" trick of 1.53
// 030721
static void FoldPropsDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) {
bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
Sci_PositionU endPos = startPos + length;
const Sci_PositionU endPos = startPos + length;
int visibleChars = 0;
Sci_Position lineCurrent = styler.GetLine(startPos);
@ -123,12 +121,12 @@ static void FoldPropsDoc(Sci_PositionU startPos, Sci_Position length, int, WordL
int lev;
for (Sci_PositionU i = startPos; i < endPos; i++) {
char ch = chNext;
const char ch = chNext;
chNext = styler[i+1];
int style = styleNext;
const int style = styleNext;
styleNext = styler.StyleAt(i + 1);
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
const bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
if (style == SCE_PROPS_SECTION) {
headerPoint = true;
@ -138,7 +136,7 @@ static void FoldPropsDoc(Sci_PositionU startPos, Sci_Position length, int, WordL
lev = SC_FOLDLEVELBASE;
if (lineCurrent > 0) {
int levelPrevious = styler.LevelAt(lineCurrent - 1);
const int levelPrevious = styler.LevelAt(lineCurrent - 1);
if (levelPrevious & SC_FOLDLEVELHEADERFLAG) {
lev = SC_FOLDLEVELBASE + 1;
@ -169,7 +167,7 @@ static void FoldPropsDoc(Sci_PositionU startPos, Sci_Position length, int, WordL
}
if (lineCurrent > 0) {
int levelPrevious = styler.LevelAt(lineCurrent - 1);
const int levelPrevious = styler.LevelAt(lineCurrent - 1);
if (levelPrevious & SC_FOLDLEVELHEADERFLAG) {
lev = SC_FOLDLEVELBASE + 1;
} else {

View file

@ -5,55 +5,77 @@
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <string>
#include <vector>
#include <map>
#include <algorithm>
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
#include "StringCopy.h"
#include "WordList.h"
#include "LexAccessor.h"
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
#include "CharacterCategory.h"
#include "LexerModule.h"
#include "OptionSet.h"
#include "SubStyles.h"
#include "DefaultLexer.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
namespace {
// Use an unnamed namespace to protect the functions and classes from name conflicts
// Use an unnamed namespace to protect the functions and classes from name conflicts
/* Notes on f-strings: f-strings are strings prefixed with f (e.g. f'') that may
have arbitrary expressions in {}. The tokens in the expressions are lexed as if
they were outside of any string. Expressions may contain { and } characters as
long as there is a closing } for every {, may be 2+ lines in a triple quoted
string, and may have a formatting specifier following a ! or :, but both !
and : are valid inside of a bracketed expression and != is a valid
expression token even outside of a bracketed expression.
When in an f-string expression, the lexer keeps track of the state value of
the f-string and the nesting count for the expression (# of [, (, { seen - # of
}, ), ] seen). f-strings may be nested (e.g. f'{ a + f"{1+2}"') so a stack of
states and nesting counts is kept. If a f-string expression continues beyond
the end of a line, this stack is saved in a std::map that maps a line number to
the stack at the end of that line. std::vector is used for the stack.
The PEP for f-strings is at https://www.python.org/dev/peps/pep-0498/
*/
struct SingleFStringExpState {
int state;
int nestingCount;
};
/* kwCDef, kwCTypeName only used for Cython */
enum kwType { kwOther, kwClass, kwDef, kwImport, kwCDef, kwCTypeName, kwCPDef };
enum literalsAllowed { litNone = 0, litU = 1, litB = 2 };
enum literalsAllowed { litNone = 0, litU = 1, litB = 2, litF = 4 };
const int indicatorWhitespace = 1;
constexpr int indicatorWhitespace = 1;
bool IsPyComment(Accessor &styler, Sci_Position pos, Sci_Position len) {
return len > 0 && styler[pos] == '#';
}
bool IsPyStringTypeChar(int ch, literalsAllowed allowed) {
bool IsPyStringTypeChar(int ch, literalsAllowed allowed) noexcept {
return
((allowed & litB) && (ch == 'b' || ch == 'B')) ||
((allowed & litU) && (ch == 'u' || ch == 'U'));
((allowed & litU) && (ch == 'u' || ch == 'U')) ||
((allowed & litF) && (ch == 'f' || ch == 'F'));
}
bool IsPyStringStart(int ch, int chNext, int chNext2, literalsAllowed allowed) {
bool IsPyStringStart(int ch, int chNext, int chNext2, literalsAllowed allowed) noexcept {
if (ch == '\'' || ch == '"')
return true;
if (IsPyStringTypeChar(ch, allowed)) {
@ -68,12 +90,63 @@ bool IsPyStringStart(int ch, int chNext, int chNext2, literalsAllowed allowed) {
return false;
}
bool IsPyFStringState(int st) noexcept {
return ((st == SCE_P_FCHARACTER) || (st == SCE_P_FSTRING) ||
(st == SCE_P_FTRIPLE) || (st == SCE_P_FTRIPLEDOUBLE));
}
bool IsPySingleQuoteStringState(int st) noexcept {
return ((st == SCE_P_CHARACTER) || (st == SCE_P_STRING) ||
(st == SCE_P_FCHARACTER) || (st == SCE_P_FSTRING));
}
bool IsPyTripleQuoteStringState(int st) noexcept {
return ((st == SCE_P_TRIPLE) || (st == SCE_P_TRIPLEDOUBLE) ||
(st == SCE_P_FTRIPLE) || (st == SCE_P_FTRIPLEDOUBLE));
}
char GetPyStringQuoteChar(int st) noexcept {
if ((st == SCE_P_CHARACTER) || (st == SCE_P_FCHARACTER) ||
(st == SCE_P_TRIPLE) || (st == SCE_P_FTRIPLE))
return '\'';
if ((st == SCE_P_STRING) || (st == SCE_P_FSTRING) ||
(st == SCE_P_TRIPLEDOUBLE) || (st == SCE_P_FTRIPLEDOUBLE))
return '"';
return '\0';
}
void PushStateToStack(int state, std::vector<SingleFStringExpState> &stack, SingleFStringExpState *&currentFStringExp) {
SingleFStringExpState single = {state, 0};
stack.push_back(single);
currentFStringExp = &stack.back();
}
int PopFromStateStack(std::vector<SingleFStringExpState> &stack, SingleFStringExpState *&currentFStringExp) noexcept {
int state = 0;
if (!stack.empty()) {
state = stack.back().state;
stack.pop_back();
}
if (stack.empty()) {
currentFStringExp = nullptr;
} else {
currentFStringExp = &stack.back();
}
return state;
}
/* Return the state to use for the string starting at i; *nextIndex will be set to the first index following the quote(s) */
int GetPyStringState(Accessor &styler, Sci_Position i, Sci_PositionU *nextIndex, literalsAllowed allowed) {
char ch = styler.SafeGetCharAt(i);
char chNext = styler.SafeGetCharAt(i + 1);
const int firstIsF = (ch == 'f' || ch == 'F');
// Advance beyond r, u, or ur prefix (or r, b, or br in Python 3.0), but bail if there are any unexpected chars
// Advance beyond r, u, or ur prefix (or r, b, or br in Python 2.7+ and r, f, or fr in Python 3.6+), but bail if there are any unexpected chars
if (ch == 'r' || ch == 'R') {
i++;
ch = styler.SafeGetCharAt(i);
@ -96,32 +169,46 @@ int GetPyStringState(Accessor &styler, Sci_Position i, Sci_PositionU *nextIndex,
*nextIndex = i + 3;
if (ch == '"')
return SCE_P_TRIPLEDOUBLE;
return (firstIsF ? SCE_P_FTRIPLEDOUBLE : SCE_P_TRIPLEDOUBLE);
else
return SCE_P_TRIPLE;
return (firstIsF ? SCE_P_FTRIPLE : SCE_P_TRIPLE);
} else {
*nextIndex = i + 1;
if (ch == '"')
return SCE_P_STRING;
return (firstIsF ? SCE_P_FSTRING : SCE_P_STRING);
else
return SCE_P_CHARACTER;
return (firstIsF ? SCE_P_FCHARACTER : SCE_P_CHARACTER);
}
}
inline bool IsAWordChar(int ch) {
return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
inline bool IsAWordChar(int ch, bool unicodeIdentifiers) {
if (IsASCII(ch))
return (IsAlphaNumeric(ch) || ch == '.' || ch == '_');
if (!unicodeIdentifiers)
return false;
// Python uses the XID_Continue set from Unicode data
return IsXidContinue(ch);
}
inline bool IsAWordStart(int ch) {
return (ch < 0x80) && (isalnum(ch) || ch == '_');
inline bool IsAWordStart(int ch, bool unicodeIdentifiers) {
if (IsASCII(ch))
return (IsUpperOrLowerCase(ch) || ch == '_');
if (!unicodeIdentifiers)
return false;
// Python uses the XID_Start set from Unicode data
return IsXidStart(ch);
}
static bool IsFirstNonWhitespace(Sci_Position pos, Accessor &styler) {
Sci_Position line = styler.GetLine(pos);
Sci_Position start_pos = styler.LineStart(line);
bool IsFirstNonWhitespace(Sci_Position pos, Accessor &styler) {
const Sci_Position line = styler.GetLine(pos);
const Sci_Position start_pos = styler.LineStart(line);
for (Sci_Position i = start_pos; i < pos; i++) {
char ch = styler[i];
const char ch = styler[i];
if (!(ch == ' ' || ch == '\t'))
return false;
}
@ -134,156 +221,200 @@ struct OptionsPython {
bool base2or8Literals;
bool stringsU;
bool stringsB;
bool stringsF;
bool stringsOverNewline;
bool keywords2NoSubIdentifiers;
bool fold;
bool foldQuotes;
bool foldCompact;
bool unicodeIdentifiers;
OptionsPython() {
whingeLevel = 0;
base2or8Literals = true;
stringsU = true;
stringsB = true;
stringsF = true;
stringsOverNewline = false;
keywords2NoSubIdentifiers = false;
fold = false;
foldQuotes = false;
foldCompact = false;
unicodeIdentifiers = true;
}
literalsAllowed AllowedLiterals() const {
literalsAllowed AllowedLiterals() const noexcept {
literalsAllowed allowedLiterals = stringsU ? litU : litNone;
if (stringsB)
allowedLiterals = static_cast<literalsAllowed>(allowedLiterals | litB);
if (stringsF)
allowedLiterals = static_cast<literalsAllowed>(allowedLiterals | litF);
return allowedLiterals;
}
};
static const char *const pythonWordListDesc[] = {
const char *const pythonWordListDesc[] = {
"Keywords",
"Highlighted identifiers",
0
nullptr
};
struct OptionSetPython : public OptionSet<OptionsPython> {
OptionSetPython() {
DefineProperty("tab.timmy.whinge.level", &OptionsPython::whingeLevel,
"For Python code, checks whether indenting is consistent. "
"The default, 0 turns off indentation checking, "
"1 checks whether each line is potentially inconsistent with the previous line, "
"2 checks whether any space characters occur before a tab character in the indentation, "
"3 checks whether any spaces are in the indentation, and "
"4 checks for any tab characters in the indentation. "
"1 is a good level to use.");
"For Python code, checks whether indenting is consistent. "
"The default, 0 turns off indentation checking, "
"1 checks whether each line is potentially inconsistent with the previous line, "
"2 checks whether any space characters occur before a tab character in the indentation, "
"3 checks whether any spaces are in the indentation, and "
"4 checks for any tab characters in the indentation. "
"1 is a good level to use.");
DefineProperty("lexer.python.literals.binary", &OptionsPython::base2or8Literals,
"Set to 0 to not recognise Python 3 binary and octal literals: 0b1011 0o712.");
"Set to 0 to not recognise Python 3 binary and octal literals: 0b1011 0o712.");
DefineProperty("lexer.python.strings.u", &OptionsPython::stringsU,
"Set to 0 to not recognise Python Unicode literals u\"x\" as used before Python 3.");
"Set to 0 to not recognise Python Unicode literals u\"x\" as used before Python 3.");
DefineProperty("lexer.python.strings.b", &OptionsPython::stringsB,
"Set to 0 to not recognise Python 3 bytes literals b\"x\".");
"Set to 0 to not recognise Python 3 bytes literals b\"x\".");
DefineProperty("lexer.python.strings.f", &OptionsPython::stringsF,
"Set to 0 to not recognise Python 3.6 f-string literals f\"var={var}\".");
DefineProperty("lexer.python.strings.over.newline", &OptionsPython::stringsOverNewline,
"Set to 1 to allow strings to span newline characters.");
"Set to 1 to allow strings to span newline characters.");
DefineProperty("lexer.python.keywords2.no.sub.identifiers", &OptionsPython::keywords2NoSubIdentifiers,
"When enabled, it will not style keywords2 items that are used as a sub-identifier. "
"Example: when set, will not highlight \"foo.open\" when \"open\" is a keywords2 item.");
"When enabled, it will not style keywords2 items that are used as a sub-identifier. "
"Example: when set, will not highlight \"foo.open\" when \"open\" is a keywords2 item.");
DefineProperty("fold", &OptionsPython::fold);
DefineProperty("fold.quotes.python", &OptionsPython::foldQuotes,
"This option enables folding multi-line quoted strings when using the Python lexer.");
"This option enables folding multi-line quoted strings when using the Python lexer.");
DefineProperty("fold.compact", &OptionsPython::foldCompact);
DefineProperty("lexer.python.unicode.identifiers", &OptionsPython::unicodeIdentifiers,
"Set to 0 to not recognise Python 3 Unicode identifiers.");
DefineWordListSets(pythonWordListDesc);
}
};
const char styleSubable[] = { SCE_P_IDENTIFIER, 0 };
LexicalClass lexicalClasses[] = {
// Lexer Python SCLEX_PYTHON SCE_P_:
0, "SCE_P_DEFAULT", "default", "White space",
1, "SCE_P_COMMENTLINE", "comment line", "Comment",
2, "SCE_P_NUMBER", "literal numeric", "Number",
3, "SCE_P_STRING", "literal string", "String",
4, "SCE_P_CHARACTER", "literal string", "Single quoted string",
5, "SCE_P_WORD", "keyword", "Keyword",
6, "SCE_P_TRIPLE", "literal string", "Triple quotes",
7, "SCE_P_TRIPLEDOUBLE", "literal string", "Triple double quotes",
8, "SCE_P_CLASSNAME", "identifier", "Class name definition",
9, "SCE_P_DEFNAME", "identifier", "Function or method name definition",
10, "SCE_P_OPERATOR", "operator", "Operators",
11, "SCE_P_IDENTIFIER", "identifier", "Identifiers",
12, "SCE_P_COMMENTBLOCK", "comment", "Comment-blocks",
13, "SCE_P_STRINGEOL", "error literal string", "End of line where string is not closed",
14, "SCE_P_WORD2", "identifier", "Highlighted identifiers",
15, "SCE_P_DECORATOR", "preprocessor", "Decorators",
16, "SCE_P_FSTRING", "literal string interpolated", "F-String",
17, "SCE_P_FCHARACTER", "literal string interpolated", "Single quoted f-string",
18, "SCE_P_FTRIPLE", "literal string interpolated", "Triple quoted f-string",
19, "SCE_P_FTRIPLEDOUBLE", "literal string interpolated", "Triple double quoted f-string",
};
}
class LexerPython : public ILexerWithSubStyles {
class LexerPython : public DefaultLexer {
WordList keywords;
WordList keywords2;
OptionsPython options;
OptionSetPython osPython;
enum { ssIdentifier };
SubStyles subStyles;
std::map<Sci_Position, std::vector<SingleFStringExpState> > ftripleStateAtEol;
public:
explicit LexerPython() :
DefaultLexer("python", SCLEX_PYTHON, lexicalClasses, ELEMENTS(lexicalClasses)),
subStyles(styleSubable, 0x80, 0x40, 0) {
}
virtual ~LexerPython() {
~LexerPython() override {
}
void SCI_METHOD Release() {
void SCI_METHOD Release() override {
delete this;
}
int SCI_METHOD Version() const {
return lvSubStyles;
int SCI_METHOD Version() const override {
return lvIdentity;
}
const char * SCI_METHOD PropertyNames() {
const char *SCI_METHOD PropertyNames() override {
return osPython.PropertyNames();
}
int SCI_METHOD PropertyType(const char *name) {
int SCI_METHOD PropertyType(const char *name) override {
return osPython.PropertyType(name);
}
const char * SCI_METHOD DescribeProperty(const char *name) {
const char *SCI_METHOD DescribeProperty(const char *name) override {
return osPython.DescribeProperty(name);
}
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val);
const char * SCI_METHOD DescribeWordListSets() {
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
const char * SCI_METHOD PropertyGet(const char *key) override {
return osPython.PropertyGet(key);
}
const char *SCI_METHOD DescribeWordListSets() override {
return osPython.DescribeWordListSets();
}
Sci_Position SCI_METHOD WordListSet(int n, const char *wl);
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess);
void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess);
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 *) {
return 0;
void *SCI_METHOD PrivateCall(int, void *) override {
return nullptr;
}
int SCI_METHOD LineEndTypesSupported() {
int SCI_METHOD LineEndTypesSupported() override {
return SC_LINE_END_TYPE_UNICODE;
}
int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) {
int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) override {
return subStyles.Allocate(styleBase, numberStyles);
}
int SCI_METHOD SubStylesStart(int styleBase) {
int SCI_METHOD SubStylesStart(int styleBase) override {
return subStyles.Start(styleBase);
}
int SCI_METHOD SubStylesLength(int styleBase) {
int SCI_METHOD SubStylesLength(int styleBase) override {
return subStyles.Length(styleBase);
}
int SCI_METHOD StyleFromSubStyle(int subStyle) {
int styleBase = subStyles.BaseStyle(subStyle);
int SCI_METHOD StyleFromSubStyle(int subStyle) override {
const int styleBase = subStyles.BaseStyle(subStyle);
return styleBase;
}
int SCI_METHOD PrimaryStyleFromStyle(int style) {
int SCI_METHOD PrimaryStyleFromStyle(int style) override {
return style;
}
void SCI_METHOD FreeSubStyles() {
void SCI_METHOD FreeSubStyles() override {
subStyles.Free();
}
void SCI_METHOD SetIdentifiers(int style, const char *identifiers) {
void SCI_METHOD SetIdentifiers(int style, const char *identifiers) override {
subStyles.SetIdentifiers(style, identifiers);
}
int SCI_METHOD DistanceToSecondaryStyles() {
int SCI_METHOD DistanceToSecondaryStyles() override {
return 0;
}
const char * SCI_METHOD GetSubStyleBases() {
const char *SCI_METHOD GetSubStyleBases() override {
return styleSubable;
}
static ILexer *LexerFactoryPython() {
return new LexerPython();
}
private:
void ProcessLineEnd(StyleContext &sc, std::vector<SingleFStringExpState> &fstringStateStack, SingleFStringExpState *&currentFStringExp, bool &inContinuedString);
};
Sci_Position SCI_METHOD LexerPython::PropertySet(const char *key, const char *val) {
@ -294,7 +425,7 @@ Sci_Position SCI_METHOD LexerPython::PropertySet(const char *key, const char *va
}
Sci_Position SCI_METHOD LexerPython::WordListSet(int n, const char *wl) {
WordList *wordListN = 0;
WordList *wordListN = nullptr;
switch (n) {
case 0:
wordListN = &keywords;
@ -315,8 +446,55 @@ Sci_Position SCI_METHOD LexerPython::WordListSet(int n, const char *wl) {
return firstModification;
}
void LexerPython::ProcessLineEnd(StyleContext &sc, std::vector<SingleFStringExpState> &fstringStateStack, SingleFStringExpState *&currentFStringExp, bool &inContinuedString) {
long deepestSingleStateIndex = -1;
unsigned long i;
// Find the deepest single quote state because that string will end; no \ continuation in f-string
for (i = 0; i < fstringStateStack.size(); i++) {
if (IsPySingleQuoteStringState(fstringStateStack[i].state)) {
deepestSingleStateIndex = i;
break;
}
}
if (deepestSingleStateIndex != -1) {
sc.SetState(fstringStateStack[deepestSingleStateIndex].state);
while (fstringStateStack.size() > static_cast<unsigned long>(deepestSingleStateIndex)) {
PopFromStateStack(fstringStateStack, currentFStringExp);
}
}
if (!fstringStateStack.empty()) {
std::pair<Sci_Position, std::vector<SingleFStringExpState> > val;
val.first = sc.currentLine;
val.second = fstringStateStack;
ftripleStateAtEol.insert(val);
}
if ((sc.state == SCE_P_DEFAULT)
|| IsPyTripleQuoteStringState(sc.state)) {
// Perform colourisation of white space and triple quoted strings at end of each line to allow
// tab marking to work inside white space and triple quoted strings
sc.SetState(sc.state);
}
if (IsPySingleQuoteStringState(sc.state)) {
if (inContinuedString || options.stringsOverNewline) {
inContinuedString = false;
} else {
sc.ChangeState(SCE_P_STRINGEOL);
sc.ForwardSetState(SCE_P_DEFAULT);
}
}
}
void SCI_METHOD LexerPython::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) {
Accessor styler(pAccess, NULL);
Accessor styler(pAccess, nullptr);
// Track whether in f-string expression; vector is used for a stack to
// handle nested f-strings such as f"""{f'''{f"{f'{1}'}"}'''}"""
std::vector<SingleFStringExpState> fstringStateStack;
SingleFStringExpState *currentFStringExp = nullptr;
const Sci_Position endPos = startPos + length;
@ -327,11 +505,11 @@ void SCI_METHOD LexerPython::Lex(Sci_PositionU startPos, Sci_Position length, in
lineCurrent--;
// Look for backslash-continued lines
while (lineCurrent > 0) {
Sci_Position eolPos = styler.LineStart(lineCurrent) - 1;
int eolStyle = styler.StyleAt(eolPos);
const Sci_Position eolPos = styler.LineStart(lineCurrent) - 1;
const int eolStyle = styler.StyleAt(eolPos);
if (eolStyle == SCE_P_STRING
|| eolStyle == SCE_P_CHARACTER
|| eolStyle == SCE_P_STRINGEOL) {
|| eolStyle == SCE_P_CHARACTER
|| eolStyle == SCE_P_STRINGEOL) {
lineCurrent -= 1;
} else {
break;
@ -349,6 +527,18 @@ void SCI_METHOD LexerPython::Lex(Sci_PositionU startPos, Sci_Position length, in
initStyle = SCE_P_DEFAULT;
}
// Set up fstate stack from last line and remove any subsequent ftriple at eol states
std::map<Sci_Position, std::vector<SingleFStringExpState> >::iterator it;
it = ftripleStateAtEol.find(lineCurrent - 1);
if (it != ftripleStateAtEol.end() && !it->second.empty()) {
fstringStateStack = it->second;
currentFStringExp = &fstringStateStack.back();
}
it = ftripleStateAtEol.lower_bound(lineCurrent);
if (it != ftripleStateAtEol.end()) {
ftripleStateAtEol.erase(it, ftripleStateAtEol.end());
}
kwType kwLast = kwOther;
int spaceFlags = 0;
styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment);
@ -383,39 +573,25 @@ void SCI_METHOD LexerPython::Lex(Sci_PositionU startPos, Sci_Position length, in
}
if (sc.atLineEnd) {
if ((sc.state == SCE_P_DEFAULT) ||
(sc.state == SCE_P_TRIPLE) ||
(sc.state == SCE_P_TRIPLEDOUBLE)) {
// Perform colourisation of white space and triple quoted strings at end of each line to allow
// tab marking to work inside white space and triple quoted strings
sc.SetState(sc.state);
}
ProcessLineEnd(sc, fstringStateStack, currentFStringExp, inContinuedString);
lineCurrent++;
if ((sc.state == SCE_P_STRING) || (sc.state == SCE_P_CHARACTER)) {
if (inContinuedString || options.stringsOverNewline) {
inContinuedString = false;
} else {
sc.ChangeState(SCE_P_STRINGEOL);
sc.ForwardSetState(SCE_P_DEFAULT);
}
}
if (!sc.More())
break;
}
bool needEOLCheck = false;
// Check for a state end
if (sc.state == SCE_P_OPERATOR) {
kwLast = kwOther;
sc.SetState(SCE_P_DEFAULT);
} else if (sc.state == SCE_P_NUMBER) {
if (!IsAWordChar(sc.ch) &&
!(!base_n_number && ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) {
if (!IsAWordChar(sc.ch, false) &&
!(!base_n_number && ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) {
sc.SetState(SCE_P_DEFAULT);
}
} else if (sc.state == SCE_P_IDENTIFIER) {
if ((sc.ch == '.') || (!IsAWordChar(sc.ch))) {
if ((sc.ch == '.') || (!IsAWordChar(sc.ch, options.unicodeIdentifiers))) {
char s[100];
sc.GetCurrent(s, sizeof(s));
int style = SCE_P_IDENTIFIER;
@ -449,7 +625,7 @@ void SCI_METHOD LexerPython::Lex(Sci_PositionU startPos, Sci_Position length, in
// We don't want to highlight keywords2
// that are used as a sub-identifier,
// i.e. not open in "foo.open".
Sci_Position pos = styler.GetStartSegment() - 1;
const Sci_Position pos = styler.GetStartSegment() - 1;
if (pos < 0 || (styler.SafeGetCharAt(pos, '\0') != '.'))
style = SCE_P_WORD2;
} else {
@ -487,10 +663,10 @@ void SCI_METHOD LexerPython::Lex(Sci_PositionU startPos, Sci_Position length, in
sc.SetState(SCE_P_DEFAULT);
}
} else if (sc.state == SCE_P_DECORATOR) {
if (!IsAWordChar(sc.ch)) {
if (!IsAWordStart(sc.ch, options.unicodeIdentifiers)) {
sc.SetState(SCE_P_DEFAULT);
}
} else if ((sc.state == SCE_P_STRING) || (sc.state == SCE_P_CHARACTER)) {
} else if (IsPySingleQuoteStringState(sc.state)) {
if (sc.ch == '\\') {
if ((sc.chNext == '\r') && (sc.GetRelative(2) == '\n')) {
sc.Forward();
@ -501,26 +677,23 @@ void SCI_METHOD LexerPython::Lex(Sci_PositionU startPos, Sci_Position length, in
// Don't roll over the newline.
sc.Forward();
}
} else if ((sc.state == SCE_P_STRING) && (sc.ch == '\"')) {
sc.ForwardSetState(SCE_P_DEFAULT);
needEOLCheck = true;
} else if ((sc.state == SCE_P_CHARACTER) && (sc.ch == '\'')) {
} else if (sc.ch == GetPyStringQuoteChar(sc.state)) {
sc.ForwardSetState(SCE_P_DEFAULT);
needEOLCheck = true;
}
} else if (sc.state == SCE_P_TRIPLE) {
} else if ((sc.state == SCE_P_TRIPLE) || (sc.state == SCE_P_FTRIPLE)) {
if (sc.ch == '\\') {
sc.Forward();
} else if (sc.Match("\'\'\'")) {
} else if (sc.Match(R"(''')")) {
sc.Forward();
sc.Forward();
sc.ForwardSetState(SCE_P_DEFAULT);
needEOLCheck = true;
}
} else if (sc.state == SCE_P_TRIPLEDOUBLE) {
} else if ((sc.state == SCE_P_TRIPLEDOUBLE) || (sc.state == SCE_P_FTRIPLEDOUBLE)) {
if (sc.ch == '\\') {
sc.Forward();
} else if (sc.Match("\"\"\"")) {
} else if (sc.Match(R"(""")")) {
sc.Forward();
sc.Forward();
sc.ForwardSetState(SCE_P_DEFAULT);
@ -528,6 +701,51 @@ void SCI_METHOD LexerPython::Lex(Sci_PositionU startPos, Sci_Position length, in
}
}
// Note if used and not if else because string states also match
// some of the above clauses
if (IsPyFStringState(sc.state) && sc.ch == '{') {
if (sc.chNext == '{') {
sc.Forward();
} else {
PushStateToStack(sc.state, fstringStateStack, currentFStringExp);
sc.ForwardSetState(SCE_P_DEFAULT);
}
needEOLCheck = true;
}
// If in an f-string expression, check for the ending quote(s)
// and end f-string to handle syntactically incorrect cases like
// f'{' and f"""{"""
if (!fstringStateStack.empty() && (sc.ch == '\'' || sc.ch == '"')) {
long matching_stack_i = -1;
for (unsigned long stack_i = 0; stack_i < fstringStateStack.size() && matching_stack_i == -1; stack_i++) {
const int stack_state = fstringStateStack[stack_i].state;
const char quote = GetPyStringQuoteChar(stack_state);
if (sc.ch == quote) {
if (IsPySingleQuoteStringState(stack_state)) {
matching_stack_i = stack_i;
} else if (quote == '"' ? sc.Match(R"(""")") : sc.Match("'''")) {
matching_stack_i = stack_i;
}
}
}
if (matching_stack_i != -1) {
sc.SetState(fstringStateStack[matching_stack_i].state);
if (IsPyTripleQuoteStringState(fstringStateStack[matching_stack_i].state)) {
sc.Forward();
sc.Forward();
}
sc.ForwardSetState(SCE_P_DEFAULT);
needEOLCheck = true;
while (fstringStateStack.size() > static_cast<unsigned long>(matching_stack_i)) {
PopFromStateStack(fstringStateStack, currentFStringExp);
}
}
}
// End of code to find the end of a state
if (!indentGood && !IsASpaceOrTab(sc.ch)) {
styler.IndicatorFill(startIndicator, sc.currentPos, indicatorWhitespace, 1);
startIndicator = sc.currentPos;
@ -541,12 +759,26 @@ void SCI_METHOD LexerPython::Lex(Sci_PositionU startPos, Sci_Position length, in
// State exit code may have moved on to end of line
if (needEOLCheck && sc.atLineEnd) {
ProcessLineEnd(sc, fstringStateStack, currentFStringExp, inContinuedString);
lineCurrent++;
styler.IndentAmount(lineCurrent, &spaceFlags, IsPyComment);
if (!sc.More())
break;
}
// If in f-string expression, check for }, :, ! to resume f-string state or update nesting count
if (currentFStringExp && !IsPySingleQuoteStringState(sc.state) && !IsPyTripleQuoteStringState(sc.state)) {
if (currentFStringExp->nestingCount == 0 && (sc.ch == '}' || sc.ch == ':' || (sc.ch == '!' && sc.chNext != '='))) {
sc.SetState(PopFromStateStack(fstringStateStack, currentFStringExp));
} else {
if (sc.ch == '{' || sc.ch == '[' || sc.ch == '(') {
currentFStringExp->nestingCount++;
} else if (sc.ch == '}' || sc.ch == ']' || sc.ch == ')') {
currentFStringExp->nestingCount--;
}
}
}
// Check for a new state starting character
if (sc.state == SCE_P_DEFAULT) {
if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
@ -554,7 +786,7 @@ void SCI_METHOD LexerPython::Lex(Sci_PositionU startPos, Sci_Position length, in
base_n_number = true;
sc.SetState(SCE_P_NUMBER);
} else if (sc.ch == '0' &&
(sc.chNext == 'o' || sc.chNext == 'O' || sc.chNext == 'b' || sc.chNext == 'B')) {
(sc.chNext == 'o' || sc.chNext == 'O' || sc.chNext == 'b' || sc.chNext == 'B')) {
if (options.base2or8Literals) {
base_n_number = true;
sc.SetState(SCE_P_NUMBER);
@ -566,7 +798,7 @@ void SCI_METHOD LexerPython::Lex(Sci_PositionU startPos, Sci_Position length, in
base_n_number = false;
sc.SetState(SCE_P_NUMBER);
}
} else if ((IsASCII(sc.ch) && isoperator(static_cast<char>(sc.ch))) || sc.ch == '`') {
} else if (isoperator(sc.ch) || sc.ch == '`') {
sc.SetState(SCE_P_OPERATOR);
} else if (sc.ch == '#') {
sc.SetState(sc.chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE);
@ -581,7 +813,7 @@ void SCI_METHOD LexerPython::Lex(Sci_PositionU startPos, Sci_Position length, in
while (nextIndex > (sc.currentPos + 1) && sc.More()) {
sc.Forward();
}
} else if (IsAWordStart(sc.ch)) {
} else if (IsAWordStart(sc.ch, options.unicodeIdentifiers)) {
sc.SetState(SCE_P_IDENTIFIER);
}
}
@ -591,10 +823,10 @@ void SCI_METHOD LexerPython::Lex(Sci_PositionU startPos, Sci_Position length, in
}
static bool IsCommentLine(Sci_Position line, Accessor &styler) {
Sci_Position pos = styler.LineStart(line);
Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
const Sci_Position pos = styler.LineStart(line);
const Sci_Position eol_pos = styler.LineStart(line + 1) - 1;
for (Sci_Position i = pos; i < eol_pos; i++) {
char ch = styler[i];
const char ch = styler[i];
if (ch == '#')
return true;
else if (ch != ' ' && ch != '\t')
@ -603,9 +835,9 @@ static bool IsCommentLine(Sci_Position line, Accessor &styler) {
return false;
}
static bool IsQuoteLine(Sci_Position line, Accessor &styler) {
int style = styler.StyleAt(styler.LineStart(line)) & 31;
return ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE));
static bool IsQuoteLine(Sci_Position line, const Accessor &styler) {
const int style = styler.StyleAt(styler.LineStart(line)) & 31;
return IsPyTripleQuoteStringState(style);
}
@ -613,7 +845,7 @@ void SCI_METHOD LexerPython::Fold(Sci_PositionU startPos, Sci_Position length, i
if (!options.fold)
return;
Accessor styler(pAccess, NULL);
Accessor styler(pAccess, nullptr);
const Sci_Position maxPos = startPos + length;
const Sci_Position maxLines = (maxPos == styler.Length()) ? styler.GetLine(maxPos) : styler.GetLine(maxPos - 1); // Requested last line
@ -625,13 +857,13 @@ void SCI_METHOD LexerPython::Fold(Sci_PositionU startPos, Sci_Position length, i
// at least one line in all cases)
int spaceFlags = 0;
Sci_Position lineCurrent = styler.GetLine(startPos);
int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, nullptr);
while (lineCurrent > 0) {
lineCurrent--;
indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, nullptr);
if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) &&
(!IsCommentLine(lineCurrent, styler)) &&
(!IsQuoteLine(lineCurrent, styler)))
(!IsCommentLine(lineCurrent, styler)) &&
(!IsQuoteLine(lineCurrent, styler)))
break;
}
int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
@ -641,7 +873,7 @@ void SCI_METHOD LexerPython::Fold(Sci_PositionU startPos, Sci_Position length, i
int prev_state = SCE_P_DEFAULT & 31;
if (lineCurrent >= 1)
prev_state = styler.StyleAt(startPos - 1) & 31;
int prevQuote = options.foldQuotes && ((prev_state == SCE_P_TRIPLE) || (prev_state == SCE_P_TRIPLEDOUBLE));
int prevQuote = options.foldQuotes && IsPyTripleQuoteStringState(prev_state);
// Process all characters to end of requested range or end of any triple quote
//that hangs over the end of the range. Cap processing in all cases
@ -655,10 +887,10 @@ void SCI_METHOD LexerPython::Fold(Sci_PositionU startPos, Sci_Position length, i
int quote = false;
if (lineNext <= docLines) {
// Information about next line is only available if not at end of document
indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
Sci_Position lookAtPos = (styler.LineStart(lineNext) == styler.Length()) ? styler.Length() - 1 : styler.LineStart(lineNext);
int style = styler.StyleAt(lookAtPos) & 31;
quote = options.foldQuotes && ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE));
indentNext = styler.IndentAmount(lineNext, &spaceFlags, nullptr);
const Sci_Position lookAtPos = (styler.LineStart(lineNext) == styler.Length()) ? styler.Length() - 1 : styler.LineStart(lineNext);
const int style = styler.StyleAt(lookAtPos) & 31;
quote = options.foldQuotes && IsPyTripleQuoteStringState(style);
}
const int quote_start = (quote && !prevQuote);
const int quote_continue = (quote && prevQuote);
@ -680,19 +912,25 @@ void SCI_METHOD LexerPython::Fold(Sci_PositionU startPos, Sci_Position length, i
// Skip past any blank lines for next indent level info; we skip also
// comments (all comments, not just those starting in column 0)
// which effectively folds them into surrounding code rather
// than screwing up folding.
// than screwing up folding. If comments end file, use the min
// comment indent as the level after
int minCommentLevel = indentCurrentLevel;
while (!quote &&
(lineNext < docLines) &&
((indentNext & SC_FOLDLEVELWHITEFLAG) ||
(lineNext <= docLines && IsCommentLine(lineNext, styler)))) {
(lineNext < docLines) &&
((indentNext & SC_FOLDLEVELWHITEFLAG) ||
(lineNext <= docLines && IsCommentLine(lineNext, styler)))) {
if (IsCommentLine(lineNext, styler) && indentNext < minCommentLevel) {
minCommentLevel = indentNext;
}
lineNext++;
indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL);
indentNext = styler.IndentAmount(lineNext, &spaceFlags, nullptr);
}
const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK;
const int levelBeforeComments = Maximum(indentCurrentLevel,levelAfterComments);
const int levelAfterComments = ((lineNext < docLines) ? indentNext & SC_FOLDLEVELNUMBERMASK : minCommentLevel);
const int levelBeforeComments = std::max(indentCurrentLevel, levelAfterComments);
// Now set all the indent levels on the lines we skipped
// Do this from end to start. Once we encounter one line
@ -703,19 +941,19 @@ void SCI_METHOD LexerPython::Fold(Sci_PositionU startPos, Sci_Position length, i
int skipLevel = levelAfterComments;
while (--skipLine > lineCurrent) {
int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL);
const int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, nullptr);
if (options.foldCompact) {
if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments)
skipLevel = levelBeforeComments;
int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG;
const int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG;
styler.SetLevel(skipLine, skipLevel | whiteFlag);
} else {
if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments &&
!(skipLineIndent & SC_FOLDLEVELWHITEFLAG) &&
!IsCommentLine(skipLine, styler))
!(skipLineIndent & SC_FOLDLEVELWHITEFLAG) &&
!IsCommentLine(skipLine, styler))
skipLevel = levelBeforeComments;
styler.SetLevel(skipLine, skipLevel);
@ -743,4 +981,4 @@ void SCI_METHOD LexerPython::Fold(Sci_PositionU startPos, Sci_Position length, i
}
LexerModule lmPython(SCLEX_PYTHON, LexerPython::LexerFactoryPython, "python",
pythonWordListDesc);
pythonWordListDesc);

View file

@ -1,5 +1,5 @@
// Scintilla source code edit control
/** @file Lexr.cxx
/** @file LexR.cxx
** Lexer for R, S, SPlus Statistics Program (Heavily derived from CPP Lexer).
**
**/
@ -24,9 +24,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsAWordChar(const int ch) {
return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');

File diff suppressed because it is too large Load diff

View file

@ -29,9 +29,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static inline bool IsAWordChar(const int ch) {
return (isalnum(ch) || ch == '?' || ch == '!' || ch == '.' || ch == '\'' || ch == '+' || ch == '-' || ch == '*' || ch == '&' || ch == '|' || ch == '=' || ch == '_' || ch == '~');

View file

@ -27,10 +27,9 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"
#include "DefaultLexer.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
static const char *const RegistryWordListDesc[] = {
0
@ -53,7 +52,7 @@ struct OptionSetRegistry : public OptionSet<OptionsRegistry> {
}
};
class LexerRegistry : public ILexer {
class LexerRegistry : public DefaultLexer {
OptionsRegistry options;
OptionSetRegistry optSetRegistry;
@ -162,49 +161,53 @@ class LexerRegistry : public ILexer {
}
public:
LexerRegistry() {}
LexerRegistry() : DefaultLexer("registry", SCLEX_REGISTRY) {}
virtual ~LexerRegistry() {}
virtual int SCI_METHOD Version() const {
return lvOriginal;
int SCI_METHOD Version() const override {
return lvIdentity;
}
virtual void SCI_METHOD Release() {
void SCI_METHOD Release() override {
delete this;
}
virtual const char *SCI_METHOD PropertyNames() {
const char *SCI_METHOD PropertyNames() override {
return optSetRegistry.PropertyNames();
}
virtual int SCI_METHOD PropertyType(const char *name) {
int SCI_METHOD PropertyType(const char *name) override {
return optSetRegistry.PropertyType(name);
}
virtual const char *SCI_METHOD DescribeProperty(const char *name) {
const char *SCI_METHOD DescribeProperty(const char *name) override {
return optSetRegistry.DescribeProperty(name);
}
virtual Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) {
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override {
if (optSetRegistry.PropertySet(&options, key, val)) {
return 0;
}
return -1;
}
virtual Sci_Position SCI_METHOD WordListSet(int, const char *) {
const char * SCI_METHOD PropertyGet(const char *key) override {
return optSetRegistry.PropertyGet(key);
}
Sci_Position SCI_METHOD WordListSet(int, const char *) override {
return -1;
}
virtual void *SCI_METHOD PrivateCall(int, void *) {
void *SCI_METHOD PrivateCall(int, void *) override {
return 0;
}
static ILexer *LexerFactoryRegistry() {
return new LexerRegistry;
}
virtual const char *SCI_METHOD DescribeWordListSets() {
const char *SCI_METHOD DescribeWordListSets() override {
return optSetRegistry.DescribeWordListSets();
}
virtual void SCI_METHOD Lex(Sci_PositionU startPos,
void SCI_METHOD Lex(Sci_PositionU startPos,
Sci_Position length,
int initStyle,
IDocument *pAccess);
virtual void SCI_METHOD Fold(Sci_PositionU startPos,
IDocument *pAccess) override;
void SCI_METHOD Fold(Sci_PositionU startPos,
Sci_Position length,
int initStyle,
IDocument *pAccess);
IDocument *pAccess) override;
};
void SCI_METHOD LexerRegistry::Lex(Sci_PositionU startPos,

View file

@ -23,9 +23,7 @@
#include "CharacterSet.h"
#include "LexerModule.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
//XXX Identical to Perl, put in common area
static inline bool isEOLChar(char ch) {
@ -346,7 +344,7 @@ static bool RE_CanFollowKeyword(const char *keyword) {
// Look at chars up to but not including endPos
// Don't look at styles in case we're looking forward
static int skipWhitespace(Sci_Position startPos,
static Sci_Position skipWhitespace(Sci_Position startPos,
Sci_Position endPos,
Accessor &styler) {
for (Sci_Position i = startPos; i < endPos; i++) {
@ -564,7 +562,7 @@ static bool sureThisIsNotHeredoc(Sci_Position lt2StartPos,
bool allow_indent;
Sci_Position target_start, target_end;
// From this point on no more styling, since we're looking ahead
if (styler[j] == '-') {
if (styler[j] == '-' || styler[j] == '~') {
allow_indent = true;
j++;
} else {
@ -890,7 +888,7 @@ static void ColouriseRbDoc(Sci_PositionU startPos, Sci_Position length, int init
chNext = chNext2;
styler.ColourTo(i, SCE_RB_OPERATOR);
if (!(strchr("\"\'`_-", chNext2) || isSafeAlpha(chNext2))) {
if (!(strchr("\"\'`_-~", chNext2) || isSafeAlpha(chNext2))) {
// It's definitely not a here-doc,
// based on Ruby's lexer/parser in the
// heredoc_identifier routine.
@ -1236,7 +1234,7 @@ static void ColouriseRbDoc(Sci_PositionU startPos, Sci_Position length, int init
if (HereDoc.State == 0) { // '<<' encountered
HereDoc.State = 1;
HereDoc.DelimiterLength = 0;
if (ch == '-') {
if (ch == '-' || ch == '~') {
HereDoc.CanBeIndented = true;
advance_char(i, ch, chNext, chNext2); // pass by ref
} else {

Some files were not shown because too many files have changed in this diff Show more