First stab at supporting syntax highlighting via wxStyledTextCtrl
This commit is contained in:
@@ -0,0 +1,113 @@
|
||||
-module(gd_sophia_editor).
|
||||
-export([new/3, get_text/1, set_text/2]).
|
||||
|
||||
-include_lib("wx/include/wx.hrl").
|
||||
|
||||
|
||||
new(Parent, Id, Opts) ->
|
||||
STC = wxStyledTextCtrl:new(Parent, [{id, Id} | Opts]),
|
||||
|
||||
%% Set up the container lexer
|
||||
wxStyledTextCtrl:setLexer(STC, ?wxSTC_LEX_CONTAINER),
|
||||
|
||||
%% Define styles
|
||||
set_colors(STC),
|
||||
%% Connect the styling event
|
||||
wxStyledTextCtrl:connect(
|
||||
STC, 'stc_styleneeded',
|
||||
[{callback, fun(Event, _) -> style_needed(Event, STC) end}]),
|
||||
STC.
|
||||
|
||||
get_text(STC) ->
|
||||
wxStyledTextCtrl:getText(STC).
|
||||
|
||||
set_text(STC, Text) ->
|
||||
wxStyledTextCtrl:setText(STC, Text),
|
||||
%% Force Scintilla to request styling for the entire text
|
||||
wxStyledTextCtrl:colourise(STC, 0, -1).
|
||||
|
||||
%% ======================================================================
|
||||
|
||||
set_colors(STC) ->
|
||||
wxStyledTextCtrl:styleClearAll(STC),
|
||||
wxStyledTextCtrl:styleSetForeground(STC, 0, {0, 0, 0}), % Default: Black
|
||||
wxStyledTextCtrl:styleSetForeground(STC, 1, {0, 0, 192}), % Keywords: Deep Blue
|
||||
wxStyledTextCtrl:styleSetForeground(STC, 2, {0, 0, 0}), % Identifiers: Black
|
||||
wxStyledTextCtrl:styleSetForeground(STC, 3, {128, 128, 128}), % Comments: Gray
|
||||
wxStyledTextCtrl:styleSetForeground(STC, 4, {163, 21, 21}), % Strings/Chars: Reddish
|
||||
wxStyledTextCtrl:styleSetForeground(STC, 5, {128, 0, 128}), % Numbers: Purple
|
||||
wxStyledTextCtrl:styleSetForeground(STC, 6, {0, 0, 0}). % Operators: Black
|
||||
|
||||
style_needed(_Event, STC) ->
|
||||
try
|
||||
StartPos = wxStyledTextCtrl:getEndStyled(STC),
|
||||
EndPos = wxStyledTextCtrl:getLength(STC),
|
||||
Text = wxStyledTextCtrl:getTextRange(STC, StartPos, EndPos),
|
||||
case so_scan:scan(Text) of
|
||||
{ok, Tokens} ->
|
||||
wxStyledTextCtrl:startStyling(STC, StartPos),
|
||||
apply_styles(STC, Tokens);
|
||||
{error, _Reason} ->
|
||||
wxStyledTextCtrl:startStyling(STC, StartPos),
|
||||
wxStyledTextCtrl:setStyling(STC, EndPos - StartPos, 0)
|
||||
end
|
||||
catch
|
||||
error:E:T ->
|
||||
dbg("CAUGHT error:~p / ~p~n", [E, T])
|
||||
end.
|
||||
|
||||
apply_styles(STC, Tokens) ->
|
||||
lists:foreach(fun(Token) -> style_token(STC, Token) end, Tokens).
|
||||
|
||||
style_token(STC, Token) ->
|
||||
{Type, Value} = type_and_value(Token),
|
||||
{Line, Col} = element(2, Token),
|
||||
Len = byte_size(to_binary(Value)),
|
||||
Style = classify_style(Type, Value),
|
||||
% Get exact position from Line and Column
|
||||
Start = wxStyledTextCtrl:positionFromLine(STC, Line - 1) + (Col - 1),
|
||||
wxStyledTextCtrl:startStyling(STC, Start),
|
||||
wxStyledTextCtrl:setStyling(STC, Len, Style).
|
||||
|
||||
to_binary(S) when is_list(S) ->
|
||||
unicode:characters_to_binary(S);
|
||||
to_binary(S) when is_binary(S) ->
|
||||
S;
|
||||
to_binary(I) when is_integer(I) ->
|
||||
integer_to_binary(I).
|
||||
|
||||
classify_style(Type, Value) ->
|
||||
case Type of
|
||||
symbol ->
|
||||
case lists:member(Value, keywords()) of
|
||||
true -> 1;
|
||||
false -> 6
|
||||
end;
|
||||
id -> 2;
|
||||
qid -> 2;
|
||||
con -> 2;
|
||||
qcon -> 2;
|
||||
tvar -> 2;
|
||||
string -> 4;
|
||||
char -> 4;
|
||||
int -> 5;
|
||||
hex -> 5;
|
||||
bytes -> 5;
|
||||
skip -> 3;
|
||||
_Other -> 1
|
||||
end.
|
||||
|
||||
type_and_value({Type,_Line,Value}) -> {Type, Value};
|
||||
type_and_value({Type, _}) -> {Type, atom_to_list(Type)}.
|
||||
|
||||
keywords() ->
|
||||
["contract", "include", "let", "switch", "type", "record", "datatype", "if",
|
||||
"elif", "else", "function", "stateful", "payable", "true", "false", "mod",
|
||||
"public", "entrypoint", "private", "indexed", "namespace", "interface",
|
||||
"main", "using", "as", "for", "hiding", "band", "bor", "bxor", "bnot"].
|
||||
|
||||
%% dbg(Fmt) ->
|
||||
%% dbg(Fmt, []).
|
||||
|
||||
dbg(Fmt, Args) ->
|
||||
io:format("~p: " ++ Fmt, [self()|Args]).
|
||||
Reference in New Issue
Block a user