From 4bb4685dd6aaec2eae2420d4d267a660c8ed449a Mon Sep 17 00:00:00 2001 From: klugier Date: Mon, 15 May 2017 21:21:13 +0000 Subject: [PATCH] .ide Refactor MacroManager by extracting logic to UscFileParser. git-svn-id: svn://ultimatepp.org/upp/trunk@11091 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/ide/MacroElement.cpp | 21 +++ uppsrc/ide/MacroManager.cpp | 244 +---------------------------------- uppsrc/ide/MacroManager.h | 87 +++++++++++++ uppsrc/ide/UscFileParser.cpp | 154 ++++++++++++++++++++++ uppsrc/ide/ide.h | 1 + uppsrc/ide/ide.upp | 4 + uppsrc/ide/idebar.cpp | 3 +- 7 files changed, 271 insertions(+), 243 deletions(-) create mode 100644 uppsrc/ide/MacroElement.cpp create mode 100644 uppsrc/ide/MacroManager.h create mode 100644 uppsrc/ide/UscFileParser.cpp diff --git a/uppsrc/ide/MacroElement.cpp b/uppsrc/ide/MacroElement.cpp new file mode 100644 index 000000000..f91aca08d --- /dev/null +++ b/uppsrc/ide/MacroElement.cpp @@ -0,0 +1,21 @@ +#include "ide.h" + +MacroElement::MacroElement(Type type, const String& fileName, int line, const String& comment) + : type(type) + , comment(comment) + , fileName(fileName) + , line(line) +{} + +Image MacroElement::GetImage(Type type) +{ + switch(type) + { + case(Type::MACRO): + return IdeImg::Macro(); + case(Type::FUNCTION): + return IdeImg::Fn(); + case(Type::UNKNOWN): + return Image(); + } +} diff --git a/uppsrc/ide/MacroManager.cpp b/uppsrc/ide/MacroManager.cpp index d1da4206a..5c9bcfdae 100644 --- a/uppsrc/ide/MacroManager.cpp +++ b/uppsrc/ide/MacroManager.cpp @@ -1,99 +1,7 @@ #include "ide.h" -class MacroElement { -public: - enum class Type { - MACRO, - FUNCTION, - UNKNOWN - }; - -public: - MacroElement(Type type, const String& fileName, int line, const String& comment); - - static Image GetImage(Type type); - -public: - Type type; - String comment; - String name; - String prototype; - String args; - String code; - String fileName; - int line; -}; - -MacroElement::MacroElement(Type type, const String& fileName, int line, const String& comment) - : type(type) - , comment(comment) - , fileName(fileName) - , line(line) -{} - -Image MacroElement::GetImage(Type type) -{ - switch(type) - { - case(Type::MACRO): - return IdeImg::Macro(); - case(Type::FUNCTION): - return IdeImg::Fn(); - case(Type::UNKNOWN): - return Image(); - } - return Image(); -} - #define METHOD_NAME "MacroManagerWindow " << UPP_FUNCTION_NAME << "(): " -using MacroList = Array; - -class MacroManagerWindow final : public WithMacroManagerLayout { - using MacroStore = ArrayMap>; - -public: - MacroManagerWindow(Ide& ide); - - void Layout() override; - -private: - void InitButtons(); - - MacroList LoadUscFile(const String& fileName); - void LoadUscDir(const String& dir, MacroList& store); - void LoadMacros(); - void ReloadGlobalMacros(); - void ReloadLocalMacros(); - - void OnMacroSel(); - void OnImport(); - void OnExport(); - void OnEditFile(); - - void ExportFiles(Index& files, const String& dir); - void FindNodeFiles(int id, Index& list); - - void ReadFunction(CParser& parser, const String& comment, const char* prototypeBegin, MacroList& list); - void ReadMacro(CParser& parser, const String& comment, const char* prototypeBegin, MacroList& list); - void FinishRead(CParser& parser, const char* prototypeBegin, MacroElement& element, MacroList& list); - -private: - static String ReadArgs(CParser& parser); - static String ReadKeyDesc(CParser& parser); - - static String GenFileOverrideMessage(const String& fileName); - -private: - // TODO: MacroManager shold not depend upon Ide instance. - // The edit logic should be outside class the same as load macros. - Ide& ide; - - TreeCtrl macrosTree; - SplitterFrame splitter; - CodeEditor editor; -}; - MacroManagerWindow::MacroManagerWindow(Ide& ide) : ide(ide) { @@ -262,152 +170,6 @@ void MacroManagerWindow::OnEditFile() Break(); } -static void FindNext(CParser& parser) -{ - while(!parser.IsEof() && !parser.IsId("fn") && !parser.IsId("macro")) - parser.SkipTerm(); -} - -void MacroManagerWindow::ReadFunction(CParser& parser, const String& comment, const char* prototypeBegin, MacroList& list) -{ - String fileName = parser.GetFileName(); - MacroElement fn(MacroElement::Type::FUNCTION, fileName, parser.GetLine(), comment); - - if(!parser.IsId()) { - FindNext(parser); - return; - } - fn.name = parser.ReadId(); - if(!parser.Char('(')) { - FindNext(parser); - return; - } - fn.args = ReadArgs(parser); - - FinishRead(parser, prototypeBegin, fn, list); -} - -void MacroManagerWindow::ReadMacro(CParser& parser, const String& comment, const char* prototypeBegin, MacroList& list) -{ - String fileName = parser.GetFileName(); - MacroElement macro(MacroElement::Type::MACRO, fileName, parser.GetLine(), comment); - - if(!parser.IsString()) { - FindNext(parser); - return; - } - macro.name = String() << (parser.IsString() ? parser.ReadString() : ""); - if(parser.Char(':')) { - if(!parser.IsString()) { - FindNext(parser); - return; - } - - macro.name << " : " << (parser.IsString() ? parser.ReadString() : ""); - } - if (!parser.IsChar('{')) - ReadKeyDesc(parser); - - FinishRead(parser, prototypeBegin, macro, list); -} - -void MacroManagerWindow::FinishRead(CParser& parser, const char* prototypeBegin, MacroElement& element, MacroList& list) -{ - const char* bodyBegin = parser.GetPtr(); - - element.prototype = String(prototypeBegin, bodyBegin); - - if (!parser.Char('{')) { - FindNext(parser); - return; - } - - Upp::SkipBlock(parser); - - if(parser.GetSpacePtr() > bodyBegin) - element.code = String(bodyBegin, parser.GetSpacePtr()); - - list.Add(element); -} - -MacroList MacroManagerWindow::LoadUscFile(const String& fileName) -{ - MacroList ret; - String fileContent = LoadFile(fileName); - if(fileContent.IsEmpty()) { - Logw() << METHOD_NAME << "Following file \"" << fileName << "\" doesn't exist or is empty."; - return ret; - } - - try { - CParser parser(fileContent, fileName); - - while (!parser.IsEof()) { - String comment = TrimLeft(String(parser.GetSpacePtr(), parser.GetPtr())); - - if (!parser.IsId()) - return ret; - - const char* prototypeBegin = parser.GetPtr(); - String id = parser.ReadId(); - - if(id.IsEqual("fn")) - ReadFunction(parser, comment, prototypeBegin, ret); - else - if(id.IsEqual("macro")) - ReadMacro(parser, comment, prototypeBegin, ret); - else - return ret; - } - } - catch (const CParser::Error& error) { - Logw() << METHOD_NAME << "Parsing file \"" << fileName << "\" failed with error: " << error << "."; - } - - return ret; -} - -String MacroManagerWindow::ReadArgs(CParser& parser) -{ - int level = 1; - parser.Char('('); - - String ret = "("; - while(level > 0 && !parser.IsEof()) { - if (parser.Char('(')) - level++; - else - if (parser.Char(')')) - level--; - else - ret << parser.GetChar(); - } - ret << ")"; - - return ret; -} - -String MacroManagerWindow::ReadKeyDesc(CParser& parser) -{ - if(!parser.IsId()) - return String(); - - String ret = parser.ReadId(); - - while(!parser.IsEof() && parser.Char('+')) { - if(parser.IsId()) - ret << "+" << parser.ReadId(); - - else - if(parser.IsNumber()) - ret << "+" << parser.ReadInt(); - else - break; - } - - return ret; -} - String MacroManagerWindow::GenFileOverrideMessage(const String& fileName) { return String(t_("Target file")) << " \"" << fileName << "\" " << t_("already exists! Do you want to overwrite it?"); @@ -417,7 +179,7 @@ void MacroManagerWindow::LoadUscDir(const String& dir, MacroList& store) { for(FindFile ff(AppendFileName(dir, "*.usc")); ff; ff.Next()) { - MacroList list = LoadUscFile(AppendFileName(dir, ff.GetName())); + auto list = UscFileParser(AppendFileName(dir, ff.GetName())).Parse(); if(list.GetCount()) store.AppendRange(list); } @@ -475,7 +237,7 @@ void MacroManagerWindow::ReloadLocalMacros() if (ToLower(GetFileExt(filePath)) != ".usc") continue; - MacroList list = LoadUscFile(filePath); + auto list = UscFileParser(filePath).Parse(); if (list.GetCount() == 0) continue; @@ -491,8 +253,6 @@ void MacroManagerWindow::ReloadLocalMacros() } } -#undef METHOD_NAME - void Ide::DoMacroManager() { MacroManagerWindow(*this).Execute(); diff --git a/uppsrc/ide/MacroManager.h b/uppsrc/ide/MacroManager.h new file mode 100644 index 000000000..cd6c1160e --- /dev/null +++ b/uppsrc/ide/MacroManager.h @@ -0,0 +1,87 @@ +// TODO: Move to separate package... + + + +class MacroElement { +public: + enum class Type { + MACRO, + FUNCTION, + UNKNOWN + }; + +public: + MacroElement(Type type, const String& fileName, int line, const String& comment); + + static Image GetImage(Type type); + +public: + Type type; + String comment; + String name; + String prototype; + String args; + String code; + String fileName; + int line; +}; + +using MacroList = Array; + +class UscFileParser final { +public: + UscFileParser(const String& filePath); + + MacroList Parse(); + +private: + void ReadFunction(CParser& parser, const String& comment, const char* prototypeBegin, MacroList& list); + void ReadMacro(CParser& parser, const String& comment, const char* prototypeBegin, MacroList& list); + void FinishRead(CParser& parser, const char* prototypeBegin, MacroElement& element, MacroList& list); + +private: + static void FindNextElement(CParser& parser); + static String ReadArgs(CParser& parser); + static String ReadKeyDesc(CParser& parser); + +private: + String filePath; +}; + +class MacroManagerWindow final : public WithMacroManagerLayout { +public: + using MacroStore = ArrayMap>; + +public: + MacroManagerWindow(Ide& ide); + + void Layout() override; + +private: + void InitButtons(); + + void LoadUscDir(const String& dir, MacroList& store); + void LoadMacros(); + void ReloadGlobalMacros(); + void ReloadLocalMacros(); + + void OnMacroSel(); + void OnImport(); + void OnExport(); + void OnEditFile(); + + void ExportFiles(Index& files, const String& dir); + void FindNodeFiles(int id, Index& list); + +private: + static String GenFileOverrideMessage(const String& fileName); + +private: + // TODO: MacroManager shold not depend upon Ide instance. + // The edit logic should be outside class the same as load macros. + Ide& ide; + + TreeCtrl macrosTree; + SplitterFrame splitter; + CodeEditor editor; +}; diff --git a/uppsrc/ide/UscFileParser.cpp b/uppsrc/ide/UscFileParser.cpp new file mode 100644 index 000000000..35572a902 --- /dev/null +++ b/uppsrc/ide/UscFileParser.cpp @@ -0,0 +1,154 @@ +#include "ide.h" + +#define METHOD_NAME "UscFileParser::" << UPP_FUNCTION_NAME << "(): " + +UscFileParser::UscFileParser(const String& filePath) + : filePath(filePath) +{} + +MacroList UscFileParser::Parse() +{ + MacroList ret; + + String fileContent = LoadFile(filePath); + if(fileContent.IsEmpty()) { + Logw() << METHOD_NAME << "Following file \"" << filePath << "\" doesn't exist or is empty."; + return ret; + } + + try { + CParser parser(fileContent, filePath); + + while (!parser.IsEof()) { + String comment = TrimLeft(String(parser.GetSpacePtr(), parser.GetPtr())); + + if (!parser.IsId()) + return ret; + + const char* prototypeBegin = parser.GetPtr(); + String id = parser.ReadId(); + + if(id.IsEqual("fn")) + ReadFunction(parser, comment, prototypeBegin, ret); + else + if(id.IsEqual("macro")) + ReadMacro(parser, comment, prototypeBegin, ret); + else + return ret; + } + } + catch (const CParser::Error& error) { + Logw() << METHOD_NAME << "Parsing file \"" << filePath << "\" failed with error: " << error << "."; + } + + return ret; +} + +void UscFileParser::ReadFunction(CParser& parser, const String& comment, const char* prototypeBegin, MacroList& list) +{ + String fileName = parser.GetFileName(); + MacroElement fn(MacroElement::Type::FUNCTION, fileName, parser.GetLine(), comment); + + if(!parser.IsId()) { + FindNextElement(parser); + return; + } + fn.name = parser.ReadId(); + if(!parser.Char('(')) { + FindNextElement(parser); + return; + } + fn.args = ReadArgs(parser); + + FinishRead(parser, prototypeBegin, fn, list); +} + +void UscFileParser::ReadMacro(CParser& parser, const String& comment, const char* prototypeBegin, MacroList& list) +{ + String fileName = parser.GetFileName(); + MacroElement macro(MacroElement::Type::MACRO, fileName, parser.GetLine(), comment); + + if(!parser.IsString()) { + FindNextElement(parser); + return; + } + macro.name = String() << (parser.IsString() ? parser.ReadString() : ""); + if(parser.Char(':')) { + if(!parser.IsString()) { + FindNextElement(parser); + return; + } + + macro.name << " : " << (parser.IsString() ? parser.ReadString() : ""); + } + if (!parser.IsChar('{')) + ReadKeyDesc(parser); + + FinishRead(parser, prototypeBegin, macro, list); +} + +void UscFileParser::FinishRead(CParser& parser, const char* prototypeBegin, MacroElement& element, MacroList& list) +{ + const char* bodyBegin = parser.GetPtr(); + + element.prototype = String(prototypeBegin, bodyBegin); + + if (!parser.Char('{')) { + FindNextElement(parser); + return; + } + + Upp::SkipBlock(parser); + + if(parser.GetSpacePtr() > bodyBegin) + element.code = String(bodyBegin, parser.GetSpacePtr()); + + list.Add(element); +} + +void UscFileParser::FindNextElement(CParser& parser) +{ + while(!parser.IsEof() && !parser.IsId("fn") && !parser.IsId("macro")) + parser.SkipTerm(); +} + +String UscFileParser::ReadArgs(CParser& parser) +{ + int level = 1; + parser.Char('('); + + String ret = "("; + while(level > 0 && !parser.IsEof()) { + if (parser.Char('(')) + level++; + else + if (parser.Char(')')) + level--; + else + ret << parser.GetChar(); + } + ret << ")"; + + return ret; +} + +String UscFileParser::ReadKeyDesc(CParser& parser) +{ + if(!parser.IsId()) + return String(); + + String ret = parser.ReadId(); + + while(!parser.IsEof() && parser.Char('+')) { + if(parser.IsId()) + ret << "+" << parser.ReadId(); + + else + if(parser.IsNumber()) + ret << "+" << parser.ReadInt(); + else + break; + } + + return ret; +} diff --git a/uppsrc/ide/ide.h b/uppsrc/ide/ide.h index e0dfd394e..f19892de7 100644 --- a/uppsrc/ide/ide.h +++ b/uppsrc/ide/ide.h @@ -306,6 +306,7 @@ void InsertPath(EditString *es); void DlSpellerLangs(DropList& dl); #include "Assist.h" +#include "MacroManager.h" void DirSel(EditField& f, FrameRight