1 /**************************************************************************
2 ** This file is part of LiteIDE
3 **
4 ** Copyright (c) 2011-2019 LiteIDE. All rights reserved.
5 **
6 ** This library is free software; you can redistribute it and/or
7 ** modify it under the terms of the GNU Lesser General Public
8 ** License as published by the Free Software Foundation; either
9 ** version 2.1 of the License, or (at your option) any later version.
10 **
11 ** This library is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 ** Lesser General Public License for more details.
15 **
16 ** In addition, as a special exception,  that plugins developed for LiteIDE,
17 ** are allowed to remain closed sourced and can be distributed under any license .
18 ** These rights are included in the file LGPL_EXCEPTION.txt in this package.
19 **
20 **************************************************************************/
21 // Module: litebuildapi.h
22 // Creator: visualfc <visualfc@gmail.com>
23 
24 #ifndef LITEBUILDAPI_H
25 #define LITEBUILDAPI_H
26 
27 #include "liteapi/liteapi.h"
28 #include <QProcessEnvironment>
29 
30 namespace LiteApi {
31 
32 class BuildAction
33 {
34 public:
BuildAction()35     BuildAction():
36         m_debug(false),
37         m_output(false),
38         m_readline(false),
39         m_separator(false),
40         m_killold(false),
41         m_navigate(false),
42         m_folder(false),
43         m_takeall(false)
44     {}
setId(const QString & id)45     void setId(const QString &id) { m_id = id; }
setOs(const QString & os)46     void setOs(const QString &os) { m_os = os; }
setMenu(const QString & menu)47     void setMenu(const QString &menu) { m_menu = menu; }
setKey(const QString & key)48     void setKey(const QString &key) { m_key = key; }
setFunc(const QString & func)49     void setFunc(const QString &func) { m_func = func; }
setCmd(const QString & cmd)50     void setCmd(const QString &cmd) { m_cmd = cmd; }
setArgs(const QString & args)51     void setArgs(const QString &args) { m_args = args; }
setSave(const QString & save)52     void setSave(const QString &save) { m_save = save; }
setDebug(const QString & text)53     void setDebug(const QString &text) {
54         m_debug = QVariant(text).toBool();
55     }
setOutput(const QString & text)56     void setOutput(const QString &text) {
57         m_output = QVariant(text).toBool();
58     }
setReadline(const QString & text)59     void setReadline(const QString &text) {
60         m_readline = QVariant(text).toBool();
61     }
setSeparator(const QString & text)62     void setSeparator(const QString &text) {
63         m_separator = QVariant(text).toBool();
64     }
setKillold(const QString & text)65     void setKillold(const QString &text) {
66         m_killold = QVariant(text).toBool();
67     }
setNavigate(const QString & text)68     void setNavigate(const QString &text) {
69         m_navigate = QVariant(text).toBool();
70     }
setFolder(const QString & text)71     void setFolder(const QString &text) {
72         m_folder = QVariant(text).toBool();
73     }
setTakeall(const QString & text)74     void setTakeall(const QString &text) {
75         m_takeall = QVariant(text).toBool();
76     }
setWork(const QString & work)77     void setWork(const QString &work) { m_work = work; }
setCodec(const QString & codec)78     void setCodec(const QString &codec) { m_codec = codec; }
setRegex(const QString & regex)79     void setRegex(const QString &regex) { m_regex = regex; }
setImg(const QString & img)80     void setImg(const QString &img) {m_img = img; }
setTask(const QStringList & task)81     void setTask(const QStringList &task) { m_task = task; }
work()82     QString work() const { return m_work; }
id()83     QString id() const { return m_id; }
os()84     QString os() const { return m_os; }
menu()85     QString menu() const { return m_menu; }
key()86     QString key() const { return m_key; }
cmd()87     QString cmd() const { return m_cmd; }
func()88     QString func() const { return m_func; }
args()89     QString args() const { return m_args; }
save()90     QString save() const { return m_save; }
isDebug()91     bool isDebug() const { return m_debug; }
isOutput()92     bool isOutput() const { return m_output; }
isReadline()93     bool isReadline() const {return m_readline; }
isSeparator()94     bool isSeparator() const { return m_separator; }
isFolder()95     bool isFolder() const { return m_folder; }
isKillOld()96     bool isKillOld() const { return m_killold; }
isNavigate()97     bool isNavigate() const { return m_navigate; }
isTakeall()98     bool isTakeall() const { return m_takeall; }
codec()99     QString codec() const { return m_codec; }
regex()100     QString regex() const { return m_regex; }
img()101     QString img() const { return m_img; }
task()102     QStringList task() const { return m_task; }
clear()103     void clear() {
104         m_id.clear();
105         m_cmd.clear();
106         m_key.clear();
107         m_args.clear();
108         m_codec.clear();
109         m_regex.clear();
110         m_img.clear();
111         m_save.clear();
112         m_task.clear();
113         m_debug = false;
114         m_output = false;
115         m_readline = false;
116         m_separator = false;
117         m_killold = false;
118         m_folder = false;
119         m_takeall = false;
120     }
isEmpty()121     bool isEmpty() {
122         return m_id.isEmpty();
123     }
isHidden()124     bool isHidden() {
125         return m_id.isEmpty() || m_id[0].isLower();
126     }
127 protected:
128     QString m_id;
129     QString m_os;
130     QString m_key;
131     QString m_cmd;
132     QString m_func;
133     QString m_args;
134     QString m_codec;
135     QString m_regex;
136     QString m_save;
137     QString m_img;
138     QString m_work;
139     QString m_menu;
140     QStringList m_task;
141     bool    m_debug;
142     bool    m_output;
143     bool    m_readline;
144     bool    m_separator;
145     bool    m_killold;
146     bool    m_navigate;
147     bool    m_folder;
148     bool    m_takeall;
149 };
150 
151 class BuildLookup
152 {
153 public:
BuildLookup()154     BuildLookup() : m_top(1)
155     {
156     }
setMimeType(const QString & type)157     void setMimeType(const QString &type) {m_type=type;}
setFile(const QString & file)158     void setFile(const QString &file) {m_file=file;}
setTop(const QString & top)159     void setTop(const QString &top) {
160         if (top.isEmpty()) {
161             return;
162         }
163         bool ok = false;
164         int value = top.toInt(&ok);
165         if (ok) {
166             m_top=value;
167         }
168     }
mimeType()169     QString mimeType() const {return m_type;}
file()170     QString file() const {return m_file;}
top()171     int top() const {return m_top;}
172 protected:
173     QString m_type;
174     QString m_file;
175     int     m_top;
176 };
177 
178 class BuildConfig
179 {
180 public:
BuildConfig()181     BuildConfig()
182     {
183     }
setId(const QString & id)184     void setId(const QString &id) { m_id = id; }
setName(const QString & name)185     void setName(const QString &name) { m_name = name; }
setValue(const QString & value)186     void setValue(const QString &value) { m_value = value; }
id()187     QString id() const { return m_id; }
name()188     QString name() const { return m_name; }
value()189     QString value() const { return m_value; }
190 protected:
191     QString m_id;
192     QString m_name;
193     QString m_value;
194 };
195 
196 class BuildCustom
197 {
198 public:
BuildCustom()199     BuildCustom() : m_hasShared(false), m_isReadOnly(false), m_isEscaped(false)
200     {
201     }
setId(const QString & id)202     void setId(const QString &id) { m_id = id; }
setName(const QString & name)203     void setName(const QString &name) { m_name = name; }
setValue(const QString & value)204     void setValue(const QString &value) { m_value = value; }
setSharedValue(const QString & value)205     void setSharedValue(const QString &value) {
206         m_hasShared = true;
207         m_sharedValue = value;
208     }
setReadOnly(const QString & value)209     void setReadOnly(const QString &value)
210     {
211         m_isReadOnly = QVariant(value).toBool();
212     }
setEscaped(const QString & value)213     void setEscaped(const QString &value)
214     {
215         m_isEscaped = QVariant(value).toBool();
216     }
id()217     QString id() const { return m_id; }
name()218     QString name() const { return m_name; }
value()219     QString value() const { return m_value; }
hasShared()220     bool hasShared() const { return m_hasShared; }
sharedValue()221     QString sharedValue() const { return m_sharedValue; }
isReadOnly()222     bool isReadOnly() const { return m_isReadOnly; }
isEscaped()223     bool isEscaped() const { return m_isEscaped; }
224 protected:
225     QString m_id;
226     QString m_name;
227     QString m_value;
228     QString m_sharedValue;
229     bool    m_hasShared;
230     bool    m_isReadOnly;
231     bool    m_isEscaped;
232 };
233 
234 class BuildTarget
235 {
236 public:
BuildTarget()237     BuildTarget()
238     {
239     }
setId(const QString & id)240     void setId(const QString &id) { m_id = id; }
setCmd(const QString & cmd)241     void setCmd(const QString &cmd) { m_cmd = cmd; }
setDebug(const QString & debug)242     void setDebug(const QString &debug) { m_debug = debug; }
setArgs(const QString & args)243     void setArgs(const QString &args) { m_args = args; }
setWork(const QString & work)244     void setWork(const QString &work) { m_work = work; }
setBuildArgs(const QString & args)245     void setBuildArgs(const QString &args) { m_buildArgs = args; }
id()246     QString id() const { return m_id; }
cmd()247     QString cmd() const { return m_cmd; }
debug()248     QString debug() const { return m_debug; }
args()249     QString args() const { return m_args; }
work()250     QString work() const { return m_work; }
buildArgs()251     QString buildArgs() const { return m_buildArgs; }
isEmpty()252     bool isEmpty() {
253         return m_id.isEmpty();
254     }
255 protected:
256     QString m_id;
257     QString m_cmd;
258     QString m_debug;
259     QString m_buildArgs;
260     QString m_args;
261     QString m_work;
262 };
263 
264 class IBuild : public QObject
265 {
266     Q_OBJECT
267 public:
QObject(parent)268     IBuild(QObject *parent = 0): QObject(parent) {}
~IBuild()269     virtual ~IBuild() {}
270     virtual QString mimeType() const = 0;
271     virtual QString id() const = 0;
272     virtual QString work() const = 0;
273     virtual QString lock() const = 0;
274     virtual QList<BuildAction*> actionList() const = 0;
275     virtual QList<BuildLookup*> lookupList() const = 0;
276     virtual QList<BuildConfig*> configList() const = 0;
277     virtual QList<BuildCustom*> customList() const = 0;
278     virtual QList<BuildTarget*>  targetList() const = 0;
279     virtual BuildAction *findAction(const QString &name) = 0;
280     virtual QList<QAction*> actions() = 0;
281 signals:
282     void buildAction(LiteApi::IBuild *build, LiteApi::BuildAction *act);
283 };
284 
285 class IBuildManager : public IManager
286 {
287     Q_OBJECT
288 public:
IManager(parent)289     IBuildManager(QObject *parent = 0) : IManager(parent) {}
290     virtual void addBuild(IBuild *build) = 0;
291     virtual void removeBuild(IBuild *build) = 0;
292     virtual IBuild *findBuild(const QString &mimeType) = 0;
293     virtual QList<IBuild*> buildList() const = 0;
294     virtual void setCurrentBuild(IBuild *build) = 0;
295     virtual IBuild *currentBuild() const = 0;
296 signals:
297     void buildChanged(LiteApi::IBuild*);
298 };
299 
300 struct TargetInfo {
301     QString buildRootPath;
302     QString targetName;
303     QString debugName;
304     QString buildArgs;
305     QString targetArgs;
306     QString targetWorkDir;
307 };
308 
309 class ILiteBuild : public IObject
310 {
311     Q_OBJECT
312 public:
ILiteBuild(QObject * parent)313     ILiteBuild(QObject *parent) : IObject(parent)
314     {
315     }
316 public:
317     virtual QString buildTag() const = 0;
318     virtual QMap<QString,QString> buildEnvMap() const = 0;
319     virtual TargetInfo getTargetInfo() = 0;
320     virtual IBuildManager *buildManager() const = 0;
321     virtual QString envValue(LiteApi::IBuild *build, const QString &value) = 0;
322     virtual QString buildPathEnvValue(LiteApi::IBuild *build, const QString &buildFilePath, const QString &value) = 0;
323     virtual void appendOutput(const QString &str, const QBrush &brush, bool active, bool updateExistsTextColor = true) = 0;
324     virtual void execCommand(const QString &cmd, const QString &args, const QString &workDir, bool updateExistsTextColor = true, bool activateOutputCheck = true, bool navigate = true, bool command = true) = 0;
325     virtual bool execGoCommand(const QStringList &args, const QString &work, bool waitFinish = true) = 0;
326 public slots:
327     virtual void execBuildAction(LiteApi::IBuild*,LiteApi::BuildAction*) = 0;
328 };
329 
sourceBuildFilePath(const QString & filePath)330 inline QString sourceBuildFilePath(const QString &filePath)
331 {
332     QFileInfo info(filePath);
333     if (info.isDir()) {
334         return info.filePath();
335     }
336     return info.path();
337 }
338 
editorBuildFilePath(IEditor * editor)339 inline QString editorBuildFilePath(IEditor *editor)
340 {
341     QString buildFilePath;
342     if (editor) {
343         QString filePath = editor->filePath();
344         if (!filePath.isEmpty()) {
345             buildFilePath = QFileInfo(filePath).path();
346         }
347     }
348     return buildFilePath;
349 }
350 
351 
getLiteBuild(LiteApi::IApplication * app)352 inline ILiteBuild *getLiteBuild(LiteApi::IApplication* app)
353 {
354     return LiteApi::findExtensionObject<ILiteBuild*>(app,"LiteApi.ILiteBuild");
355 }
356 
getGoBuild(LiteApi::IApplication * app)357 inline IBuild *getGoBuild(LiteApi::IApplication *app)
358 {
359     ILiteBuild *build = getLiteBuild(app);
360     if (!build) {
361         return 0;
362     }
363     return build->buildManager()->findBuild("text/x-gosrc");
364 }
365 
parserArgumentValue(const QString & opt,const QString & text)366 inline QString parserArgumentValue(const QString &opt, const QString &text)
367 {
368     int pos = text.indexOf(opt);
369     if (pos == -1) {
370         return QString();
371     }
372     QString value = text.mid(pos+opt.length());
373     if (value.startsWith('=')) {
374         value = value.mid(1);
375     } else if (value.startsWith(' ')) {
376         value = value.trimmed();
377     }
378     if (value.isEmpty()) {
379         return QString();
380     }
381     if (value.startsWith('\'')) {
382         int pos = value.indexOf('\'',1);
383         if (pos != -1) {
384             return value.left(pos+1);
385         }
386     } else if (value.startsWith('\"')) {
387         int pos = value.indexOf('\"',1);
388         if (pos != -1) {
389             return value.left(pos+1);
390         }
391     } else {
392         int pos = value.indexOf(' ');
393         if (pos != -1) {
394             return value.left(pos);
395         }
396         return value;
397     }
398     return QString();
399 }
400 
getGoBuildFlagsArgument(LiteApi::IApplication * app,const QString & buildFilePath,const QString & opt)401 inline QString getGoBuildFlagsArgument(LiteApi::IApplication *app, const QString &buildFilePath, const QString &opt)
402 {
403     ILiteBuild *liteBuild = getLiteBuild(app);
404     LiteApi::IBuild *build = getGoBuild(app);
405     if (!liteBuild || !build ) {
406         return QString();
407     }
408     QString value = liteBuild->buildPathEnvValue(build,buildFilePath,"$(BUILDFLAGS)");
409     QString tags = parserArgumentValue(opt,value);
410     if (tags.isEmpty()) {
411         value = liteBuild->buildPathEnvValue(build,buildFilePath,"$(BUILDARGS)");
412         tags = parserArgumentValue(opt,value);
413     }
414     return tags;
415 }
416 
getGoBuildFlagsArgument(LiteApi::IApplication * app,LiteApi::IEditor * editor,const QString & opt)417 inline QString getGoBuildFlagsArgument(LiteApi::IApplication *app, LiteApi::IEditor *editor, const QString &opt)
418 {
419     ILiteBuild *liteBuild = getLiteBuild(app);
420     if (!liteBuild) {
421         return QString();
422     }
423     QString buildFilePath = editorBuildFilePath(editor);
424     return getGoBuildFlagsArgument(app,buildFilePath,opt);
425 }
426 
427 } //namespace LiteApi
428 
429 
430 #endif //LITEBUILDAPI_H
431 
432