ide: HTML/XML highlightitinh finalized

git-svn-id: svn://ultimatepp.org/upp/trunk@7390 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2014-05-19 18:17:40 +00:00
parent 1674d6812d
commit b813e3ce92
10 changed files with 157 additions and 56 deletions

View file

@ -182,4 +182,15 @@ Vector<IfState> CSyntax::PickIfStack()
return pick(ifstack);
}
void CSyntax::CheckSyntaxRefresh(CodeEditor& e, int pos, const WString& text)
{
for(const wchar *s = text; *s; s++) {
if(*s == '{' || *s == '(' || *s == '[' || *s == '/' || *s == '*' ||
*s == '}' || *s == ')' || *s == ']' || *s == '\\') {
e.Refresh();
break;
}
}
}
END_UPP_NAMESPACE

View file

@ -13,9 +13,9 @@ void RegisterCSyntax(const char *id, int kind,
EditorSyntax::Register(id, callback1(CreateCSyntax, kind), exts, description);
}
void CreateTagSyntax(One<EditorSyntax>& e)
void CreateTagSyntax(One<EditorSyntax>& e, bool html)
{
e.Create<XmlSyntax>();
e.Create<TagSyntax>().Html(html);
}
INITBLOCK {
@ -34,8 +34,8 @@ INITBLOCK {
RegisterCSyntax("usc", CSyntax::HIGHLIGHT_USC, "*.usc", "U++ widget definitions (.usc)");
RegisterCSyntax("calc", CSyntax::HIGHLIGHT_CALC, "", "");
EditorSyntax::Register("xml", callback(CreateTagSyntax), "*.xml", "XML (.xml)");
EditorSyntax::Register("html", callback(CreateTagSyntax), "*.html *.htm", "HTML (.html)");
EditorSyntax::Register("xml", callback1(CreateTagSyntax, false), "*.xml", "XML (.xml)");
EditorSyntax::Register("html", callback1(CreateTagSyntax, true), "*.html *.htm", "HTML (.html)");
}
END_UPP_NAMESPACE

View file

@ -8,6 +8,7 @@ public:
virtual bool CanAssist() const;
virtual void Highlight(const wchar *s, const wchar *end, HighlightOutput& hls,
CodeEditor *editor, int line, int pos);
virtual void CheckSyntaxRefresh(CodeEditor& e, int pos, const WString& text);
virtual Vector<IfState> PickIfStack(); // TODO: Refactor?
private:

View file

@ -75,32 +75,32 @@ inline bool RBR(int c) {
return isbrkt(c);
}
void CodeEditor::CheckBraces(const WString& text)
void CodeEditor::CheckSyntaxRefresh(int pos, const WString& text)
{
for(const wchar *s = text; *s; s++)
if(*s == '{' || *s == '(' || *s == '[' || *s == '/' || *s == '*' ||
*s == '}' || *s == ')' || *s == ']' || *s == '\\') {
Refresh();
break;
}
GetSyntax(GetLine(pos))->CheckSyntaxRefresh(*this, pos, text);
}
void CodeEditor::PostInsert(int pos, const WString& text) {
if(check_edited)
bar.SetEdited(GetLine(pos));
if(IsFullRefresh()) return;
if(text.GetCount() > 200)
if(text.GetCount() > 200 || text.Find('\n') >= 0)
Refresh();
else
CheckBraces(text);
CheckSyntaxRefresh(pos, text);
}
void CodeEditor::PreRemove(int pos, int size) {
if(IsFullRefresh()) return;
if(size > 200)
Refresh();
else
CheckBraces(GetW(pos, size));
else {
WString text = GetW(pos, size);
if(text.Find('\n') >= 0)
Refresh();
else
CheckSyntaxRefresh(pos, text);
}
}
void CodeEditor::PostRemove(int pos, int size) {

View file

@ -169,7 +169,7 @@ struct FindReplaceDlg : WithIDEFindReplaceLayout<TopWindow> {
#include "Syntax.h"
#include "CSyntax.h"
#include "XmlSyntax.h"
#include "TagSyntax.h"
class CodeEditor : public LineEdit,
public HighlightSetup //TODO:SYNTAX
@ -280,7 +280,7 @@ protected:
void FindWildcard();
void ReplaceWildcard();
void InsertWildcard(int c);
void CheckBraces(const WString& text);
void CheckSyntaxRefresh(int pos, const WString& text);
void SetFound(int fi, int type, const WString& text);

View file

@ -21,9 +21,9 @@ file
CHighlight.cpp,
CLogic.cpp,
CRegister.icpp,
Xml readonly separator,
XmlSyntax.h,
XmlSyntax.cpp,
TagSyntax readonly separator,
TagSyntax.h,
TagSyntax.cpp,
Editor readonly separator,
EditorBar.cpp,
FindReplace.cpp,

View file

@ -50,6 +50,10 @@ Color EditorSyntax::IfColor(char c)
}
}
void EditorSyntax::CheckSyntaxRefresh(CodeEditor& e, int pos, const WString& text)
{
}
EditorSyntax::~EditorSyntax() {}
END_UPP_NAMESPACE

View file

@ -101,6 +101,7 @@ public:
virtual void Serialize(Stream& s);
virtual void IndentInsert(CodeEditor& editor, int chr, int count);
virtual bool CheckBrackets(CodeEditor& e, int& bpos0, int& bpos); // TODO: Replace with generic mechanism
virtual void CheckSyntaxRefresh(CodeEditor& e, int pos, const WString& text);
virtual bool CanAssist() const;
virtual void Highlight(const wchar *s, const wchar *end, HighlightOutput& hls,
CodeEditor *editor, int line, int pos);

View file

@ -2,13 +2,13 @@
NAMESPACE_UPP
void XmlSyntax::Clear()
void TagSyntax::Clear()
{
hl_ink = INK_NORMAL;
hl_paper = PAPER_NORMAL;
}
void XmlSyntax::Put0(int ink, int n, int paper)
void TagSyntax::Put0(int ink, int n, int paper)
{
if(hout)
hout->Put(n, hl_style[ink], hl_style[paper]);
@ -19,7 +19,7 @@ inline static bool IsXmlNameChar(int c)
return IsAlNum(c) || c == '.' || c == '-' || c == '_' || c == ':';
}
const wchar *XmlSyntax::Spaces(const wchar *s, const wchar *e)
const wchar *TagSyntax::Spaces(const wchar *s, const wchar *e)
{
while(s < e && IsSpace(*s)) {
s++;
@ -28,7 +28,7 @@ const wchar *XmlSyntax::Spaces(const wchar *s, const wchar *e)
return s;
}
void XmlSyntax::DoScript(const wchar *s, const wchar *e)
void TagSyntax::DoScript(const wchar *s, const wchar *e)
{
if(hout)
script.Highlight(s, e, *hout, NULL, 0, 0);
@ -36,25 +36,75 @@ void XmlSyntax::DoScript(const wchar *s, const wchar *e)
script.ScanSyntax(s, e, 0, 0);
}
void XmlSyntax::Do(const wchar *s, const wchar *e)
inline
static const wchar *sSkipSpaces(const wchar *s, const wchar *e)
{
while(s < e && IsSpace(*s))
s++;
return s;
}
inline bool cmp_wi(const wchar *s, const wchar *t, int len)
{
while(len--) {
if(ToUpper(*s++) != ToUpper(*t++))
return false;
}
return true;
}
inline
bool IsEndTag(const wchar *s, const wchar *e, const wchar *tag, int len)
{
if(*s != '<' || s >= e)
return false;
s = sSkipSpaces(s + 1, e);
if(*s != '/' || s >= e)
return false;
s = sSkipSpaces(s + 1, e);
return s < e && e - s >= len && cmp_wi(s, tag, len);
}
const wchar *IsScriptEnd(const wchar *s, const wchar *e, bool script)
{
while(s < e) {
int c = *s;
if(c == '\"' || c == '\'') {
s++;
while(s < e && *s != c) {
if(*s == '\\' && s + 1 < e)
s += 2;
else
s++;
}
}
else {
static WString s_script("script");
static WString s_style("style");
const WString& tag = script ? s_script : s_style;
if(IsEndTag(s, e, ~tag, tag.GetLength()))
return s;
}
s++;
}
return NULL;
}
void TagSyntax::Do(const wchar *s, const wchar *e)
{
doscript:
if(status == SCRIPT) { // TODO: Improve ending detection...
static WString h1 = "</script>";
static WString h2 = "</style>";
int q = find(s, e - s, ~h1, h1.GetLength(), 0);
if(q < 0)
q = find(s, e - s, ~h2, h2.GetLength(), 0);
if(q < 0) {
DoScript(s, e);
return;
}
else {
DoScript(s, s + q);
s += q;
const wchar *q = IsScriptEnd(s, e, script_type == JS);
if(q) {
DoScript(s, q);
s = q;
status = TEXT;
Set(INK_NORMAL);
}
else {
DoScript(s, e);
return;
}
}
while(s < e) {
s = Spaces(s, e);
@ -113,15 +163,20 @@ doscript:
Put();
Set(INK_NORMAL);
status = TEXT;
if(tagname == "script") {
script.SetHighlight(CSyntax::HIGHLIGHT_JAVASCRIPT);
status = SCRIPT;
goto doscript;
}
if(tagname == "style") {
script.SetHighlight(CSyntax::HIGHLIGHT_CSS);
status = SCRIPT;
goto doscript;
if(html) {
if(tagname == "script") {
script.SetHighlight(CSyntax::HIGHLIGHT_JAVASCRIPT);
status = SCRIPT;
script_type = JS;
goto doscript;
}
else
if(tagname == "style") {
script.SetHighlight(CSyntax::HIGHLIGHT_CSS);
status = SCRIPT;
script_type = CSS;
goto doscript;
}
}
}
else
@ -131,7 +186,9 @@ doscript:
tagname.Cat(*s++);
Put();
}
if(*tagname != '/')
if(*tagname == '/')
status = ENDTAG;
else
status = TAG;
}
else
@ -179,25 +236,46 @@ doscript:
}
}
void XmlSyntax::ScanSyntax(const wchar *s, const wchar *e, int, int)
void TagSyntax::CheckSyntaxRefresh(CodeEditor& e, int pos, const WString& text)
{
script.CheckSyntaxRefresh(e, pos, text);
for(const wchar *s = text; *s; s++)
if(*s == '<' || *s == '>' || *s == '/') {
e.Refresh();
return;
}
int l = max(pos - 6, 0);
int h = min(pos + text.GetLength() + 6, e.GetLength());
if(h - l > 200) {
e.Refresh();
return;
}
WString w = ToLower(e.GetW(l, h - l));
if(w.Find("style") >= 0 || w.Find("script") >= 0)
e.Refresh();
}
void TagSyntax::ScanSyntax(const wchar *s, const wchar *e, int, int)
{
Do(s, e);
}
void XmlSyntax::Highlight(const wchar *s, const wchar *end, HighlightOutput& hls, CodeEditor *editor, int line, int pos)
void TagSyntax::Highlight(const wchar *s, const wchar *end, HighlightOutput& hls, CodeEditor *editor, int line, int pos)
{
hout = &hls;
Do(s, end);
hout = NULL;
}
void XmlSyntax::Serialize(Stream& s)
void TagSyntax::Serialize(Stream& s)
{
s % hl_ink
% hl_paper
% status
% tagname
% script;
% script
% script_type
% html;
}
END_UPP_NAMESPACE

View file

@ -1,21 +1,25 @@
class XmlSyntax : public EditorSyntax { // Tag based languages (XML, HTML)
class TagSyntax : public EditorSyntax { // Tag based languages (XML, HTML)
public:
virtual void Clear();
virtual void ScanSyntax(const wchar *ln, const wchar *e, int line, int tab_size);
virtual void Serialize(Stream& s);
virtual void Highlight(const wchar *s, const wchar *end, HighlightOutput& hls,
CodeEditor *editor, int line, int pos);
virtual void CheckSyntaxRefresh(CodeEditor& e, int pos, const WString& text);
private:
enum { TEXT, TAG0, TAG, ATTR, COMMENT, DECL, PI, SCRIPT };
enum { TEXT, TAG0, TAG, ENDTAG, ATTR, COMMENT, DECL, PI, SCRIPT };
bool html;
int status;
int hl_ink;
int hl_paper;
String tagname;
CSyntax script;
CSyntax script; // for <style> or <script>
enum { CSS, JS };
int script_type;
HighlightOutput *hout;
@ -29,5 +33,7 @@ private:
void SetPut(int ink, int n = 1, int paper = PAPER_NORMAL) { Set(ink, paper); Put(n); }
public:
XmlSyntax() { Clear(); hout = NULL; }
void Html(bool b) { html = b; }
TagSyntax() { Clear(); hout = NULL; html = true; }
};