1 #ifndef Header_Build_Manager
2 #define Header_Build_Manager
3 
4 #include "mostQtHeaders.h"
5 
6 class ProcessX;
7 
8 struct PreviewSource {
9 	QString text;
10 	int fromLine, toLine;
11 	bool atCursor;
PreviewSourcePreviewSource12 	PreviewSource(): fromLine(0), toLine(0), atCursor(false) {}
PreviewSourcePreviewSource13 	PreviewSource(const QString &text, int fromLine, int toLine, bool atCursor):
14 		text(text), fromLine(fromLine), toLine(toLine), atCursor(atCursor) {}
15 };
16 
17 enum LatexCompileResult {
18 	LCR_NORMAL = 0,
19 	LCR_ERROR,
20 	LCR_RERUN,
21 	LCR_RERUN_WITH_BIBLIOGRAPHY
22 };
23 Q_DECLARE_METATYPE(LatexCompileResult)
24 
25 
26 enum RunCommandFlag {
27 	RCF_SHOW_STDOUT = 1,    //bibliography command (=> show stdout)
28 	RCF_COMPILES_TEX = 4, //latex command, show the log
29 	RCF_RERUNNABLE = 8, 	// set if the command provides output information that
30 				// tells you when it must be rerun. Usually RCF_RERUNNABLE
31 				// is set iff RCF_COMPILES_TEX is set, except for latexmk.
32 	RCF_RERUN = 16,         // User has allowed program rerun through the command settings
33 	RCF_CHANGE_PDF = 32,    //pdflatex (=> lock pdf)
34 	RCF_SINGLE_INSTANCE = 64,//viewer (=> start only once)
35 	RCF_WAITFORFINISHED = 128
36 };
37 Q_DECLARE_FLAGS(RunCommandFlags, RunCommandFlag)
38 
39 struct CommandToRun {
40 	QString command;
41 	QString parentCommand;
42 	RunCommandFlags flags;
43 	CommandToRun();
44 	CommandToRun(const QString &cmd);
45 };
46 
47 struct ExpandedCommands {
48 	QString primaryCommand;
49 	QList<CommandToRun> commands;
50 };
51 
52 typedef QString (*GuessCommandLineFunc) ();
53 struct CommandInfo {
54 	CommandInfo();
55 	QString id;
56 	QString commandLine;
57 
58 	QString defaultArgs;
59 	QString displayName;
60 	bool user;
61 	bool meta;
62 	bool rerunCompiler;
63 
64 	QStringList metaSuggestionList;
65 	QStringList simpleDescriptionList;
66 
67     QString guessCommandLine(const QString texpath="") const;
68 	//sets a command (accepts tr("<unknown>"))
69 	void setCommandLine(const QString &newCmd);
70 
71 	QString getPrettyCommand() const;
getBaseNameCommandInfo72 	QString getBaseName() const { return baseName; }
73     QString getProgramName() const;
74     QString getProgramNameUnquoted() const;
75 private:
76 	friend class BuildManager;
77 	QString baseName;
78 	GuessCommandLineFunc guessFunc;
79 	QString deprecatedConfigName;
80 public:
81 	static QString getProgramName(const QString &commandLine);
82 	static QString getProgramNameUnquoted(const QString &commandLine);
83 };
84 
85 struct ExpandingOptions {
86 	ExpandingOptions(const QFileInfo &mainFile, const QFileInfo &currentFile = QFileInfo(), const int currentLine = 0);
87 	const QFileInfo mainFile;
88 	const QFileInfo currentFile;
89 	const int currentLine;
90 	int nestingDeep;
91 	bool canceled;
92 	struct ParameterOverride {
93 		QList<QPair<QString, QString> > replace;
94 		QStringList append;
95 		QStringList remove;
96 		bool removeAll;
97 	};
98 	ParameterOverride override;
99 };
100 
101 typedef QHash<QString, CommandInfo> CommandMapping;
102 
103 class ConfigManagerInterface;
104 
105 class BuildManager: public QObject
106 {
107 	Q_OBJECT
108 
109 public:
110 	BuildManager();
111 	~BuildManager();
112 
113 	static const QString TXS_CMD_PREFIX;
114 	static const QString CMD_LATEX, CMD_PDFLATEX, CMD_XELATEX, CMD_LUALATEX, CMD_LATEXMK;
115 	static const QString CMD_VIEW_DVI, CMD_VIEW_PS, CMD_VIEW_PDF, CMD_VIEW_LOG;
116     static const QString CMD_DVIPNG, CMD_DVIPS, CMD_DVIPDF, CMD_PS2PDF, CMD_GS, CMD_MAKEINDEX, CMD_TEXINDY, CMD_MAKEGLOSSARIES, CMD_METAPOST, CMD_ASY, CMD_BIBTEX, CMD_BIBTEX8, CMD_BIBER, CMD_SVN, CMD_SVNADMIN, CMD_GIT, CMD_TEXDOC;
117 	static const QString CMD_COMPILE, CMD_VIEW, CMD_BIBLIOGRAPHY, CMD_INDEX, CMD_GLOSSARY, CMD_QUICK, CMD_RECOMPILE_BIBLIOGRAPHY;
118 	static const QString CMD_VIEW_PDF_INTERNAL, CMD_INTERNAL_PRE_COMPILE, CMD_CONDITIONALLY_RECOMPILE_BIBLIOGRAPHY, CMD_TERMINAL_EXTERNAL;
119 
120 	static QString chainCommands(const QString &a);
121 	static QString chainCommands(const QString &a, const QString &b);
122 	static QString chainCommands(const QString &a, const QString &b, const QString &c);
123 	static QString chainCommands(const QString &a, const QString &b, const QString &c, const QString &d);
124 
125 	static QStringList splitOptions(const QString &s);
126 	static QString findFileInPath(QString fileName);
127 	static QString replaceEnvironmentVariables(const QString &s);
128 	static QString replaceEnvironmentVariables(const QString &s, const QHash<QString, QString> &variables, bool compareNamesToUpper);
129 	static QString resolvePaths(QString paths);
130 	static QStringList parseExtendedCommandLine(QString str, const QFileInfo &mainFile, const QFileInfo &currentFile = QFileInfo(), int currentLine = 0);
131 	static QFileInfo parseExtendedSelectFile(QString &command, const QFileInfo &mainFile, const QFileInfo &currentFile);
132 	static QString extractOutputRedirection(const QString &commandLine, QString &stdOut, QString &stdErr);
133 	ExpandedCommands expandCommandLine(const QString &str, ExpandingOptions &expandingOptions);
134 	RunCommandFlags getSingleCommandFlags(const QString &command) const;
135 	bool hasCommandLine(const QString &program);
136 
137 	void registerOptions(ConfigManagerInterface &cmi);
138     void readSettings(QSettings &settings);
139 	void saveSettings(QSettings &settings);
140     void resetDefaultCommands(const QString texPath);
141 
142 	void checkLatexConfiguration(bool &noWarnAgain);
143 
144 
145 public slots:
146     bool runCommand(const QString &unparsedCommandLine, const QFileInfo &mainFile, const QFileInfo &currentFile = QFileInfo(), int currentLine = 0, QString *buffer = nullptr, QTextCodec *codecForBuffer = nullptr, QString *errorMsg = nullptr);
147 	Q_INVOKABLE void killCurrentProcess();
148 private:
149 	bool checkExpandedCommands(const ExpandedCommands &expandedCommands);
150     bool runCommandInternal(const ExpandedCommands &expandedCommands, const QFileInfo &mainFile, QString *buffer = nullptr, QTextCodec *codecForBuffer = nullptr, QString *errorMsg = nullptr);
151 public:
152 	//creates a process object with the given command line (after it is changed by an implcit call to parseExtendedCommandLine)
153 	//ProcessX* newProcess(const QString &unparsedCommandLine, const QString &mainFile, const QString &currentFile, int currentLine=0, bool singleInstance = false);
154 	//QList<ProcessX*> newProcesses(const QString &unparsedCommandLine, const QString &mainFile, const QString &currentFile, int currentLine=0, bool singleInstance = false);
155     Q_INVOKABLE ProcessX *firstProcessOfDirectExpansion(const QString &command, const QFileInfo &mainfile, const QFileInfo &currentFile = QFileInfo(), int currentLine = 0, bool nonstop=false);
156 
157 	Q_INVOKABLE ProcessX *newProcessInternal(const QString &fullCommandLine, const QFileInfo &mainFile, bool singleInstance = false);
158 public:
159 	Q_INVOKABLE bool waitForProcess(ProcessX *p);
160 	Q_INVOKABLE bool waitingForProcess() const;
161 
162 	static QString createTemporaryFileName(); //don't forget to remove the file!
163 
164     void preview(const QString &preamble, const PreviewSource &source, const QString &masterFile, QTextCodec *outputCodec = nullptr);
165 	void clearPreviewPreambleCache();
166 
167 	Q_INVOKABLE bool isCommandDirectlyDefined(const QString &id) const;
168 	CommandInfo getCommandInfo(const QString &id) const;
169 	QString editCommandList(const QString &list, const QString &excludeId = "");
170 	CommandMapping getAllCommands();
171 	QStringList getCommandsOrder();
172 	void setAllCommands(const CommandMapping &commands, const QStringList &userOrder);
173 	QString guessCompilerFromProgramMagicComment(const QString &program);
174 	QString guessViewerFromProgramMagicComment(const QString &program);
175 
176 	int maxExpandingNestingDeep;
177 
178 	int previewCompileTimeOut;
179 
180 	int deprecatedQuickmode;
181 	QStringList deprecatedUserToolCommands, deprecatedUserToolNames;
182 	QStringList userToolOrder, userToolDisplayNames;
183 	enum Dvi2PngMode { DPM_DVIPNG, DPM_DVIPNG_FOLLOW, DPM_DVIPS_GHOSTSCRIPT, DPM_EMBEDDED_PDF};
184 	Dvi2PngMode dvi2pngMode;
185 	enum SaveFilesBeforeCompiling {SFBC_ALWAYS, SFBC_ONLY_CURRENT_OR_NAMED, SFBC_ONLY_NAMED};
186 	SaveFilesBeforeCompiling saveFilesBeforeCompiling;
187 	bool previewRemoveBeamer, previewPrecompilePreamble;
188 private slots:
189 	void singleInstanceCompleted(int status);
190 	void preamblePrecompileCompleted(int status);
191 	void latexPreviewCompleted(int status);
192 	void dvi2psPreviewCompleted(int status);
193 	void conversionPreviewCompleted(int status);
194     void PreviewLatexCompleted(int status);
195 	void commandLineRequestedDefault(const QString &cmdId, QString *result, bool *user);
196 	void runInternalCommandThroughProcessX();
197 	void emitEndRunningSubCommandFromProcessX(int);
198 private:
199 	bool testAndRunInternalCommand(const QString &cmd, const QFileInfo &mainFile);
200 signals:
201 	void hideSplash();
202 	void processNotification(const QString &message);
203     void clearLogs();
204 	void previewAvailable(const QString &filename, const PreviewSource &source);
205 
206     void commandLineRequested(const QString &cmdId, QString *result, bool *user = nullptr);
207 	void runInternalCommand(const QString &cmdId, const QFileInfo &mainfile, const QString &options);
208 
209 	void latexCompiled(LatexCompileResult *rerun);
210 	void beginRunningCommands(const QString &commandMain, bool latex, bool pdf, bool asyncPdf);
211 	void beginRunningSubCommand(ProcessX *p, const QString &commandMain, const QString &subCommand, const RunCommandFlags &flags);
212 	void endRunningSubCommand(ProcessX *p, const QString &commandMain, const QString &subCommand, const RunCommandFlags &flags);
213 	void endRunningCommands(const QString &commandMain, bool latex, bool pdf, bool asyncPdf);
214     void buildRunning(bool c);
215 private:
216 
217 	void initDefaultCommandNames();
218 	static QString guessTerminalExternal(void);
219 
220     CommandInfo &registerCommand(const QString &id, const QString &basename, const QString &displayName, const QString &args, const QString &oldConfig = "", GuessCommandLineFunc guessFunc = nullptr, bool user = false);
221 	CommandInfo &registerCommand(const QString &id, const QString &displayname, const QStringList &alternatives, const QString &oldConfig = "", const bool metaCommand = true, const QStringList simpleDescriptions = QStringList());
222 	Q_INVOKABLE QString getCommandLine(const QString &id, bool *user);
223 	friend class ProcessX;
224 	CommandMapping commands;
225 	QStringList internalCommands, commandSortingsOrder;
226 	QMap<QString, ProcessX *> runningCommands;
227 	QPointer<ProcessX> processWaitedFor;
228 
229 	QStringList latexCommands, rerunnableCommands, pdfCommands, stdoutCommands, viewerCommands;
230 public:
231 	static int autoRerunLatex;
232 	static bool showLogInCaseOfCompileError;
233 	static bool m_replaceEnvironmentVariables;
234 	static bool m_interpetCommandDefinitionInMagicComment;
235 	static bool m_supportShellStyleLiteralQuotes;
236 	static bool singleViewerInstance;
237 	static QString autoRerunCommands;
238 	static QString additionalSearchPaths, additionalLogPaths, additionalPdfPaths;
239 
240 	static QString findCompiledFile(const QString &compiledFilename, const QFileInfo &mainFile);
addPreviewFileName(QString fn)241 	void addPreviewFileName(QString fn)
242 	{
243 		if (!previewFileNames.contains(fn))
244 			previewFileNames.append(fn);
245 	}
246 
247 private:
248 	QStringList previewFileNames;
249 	QMap<QString, PreviewSource> previewFileNameToSource;
250 	QHash<QString, QString> preambleHash;
251 	void removePreviewFiles(QString elemName);
252 #ifdef Q_OS_WIN32
253 	unsigned long int pidInst;
254 	Q_INVOKABLE bool executeDDE(QString ddePseudoURL);
255 #endif
256 };
257 
258 //#define PROFILE_PROCESSES
Q_DECLARE_METATYPE(ProcessX *)259 Q_DECLARE_METATYPE(ProcessX *)
260 //this process can handle dde and normal commands
261 class ProcessX: public QProcess
262 {
263 	Q_OBJECT
264 
265 public:
266     ProcessX(BuildManager *parent = nullptr, const QString &assignedCommand = "", const QString &fileToCompile = "");
267 	static QString reformatShellLiteralQuotes(QString cmd);
268 	void startCommand();
269 	bool waitForStarted(int timeOut = 30000);
270 	const QString &getFile();
271 	const QString &getCommandLine();
272 	bool showStdout() const;
273 	void setShowStdout(bool show);
274     QString *getStdoutBuffer();
275     Q_INVOKABLE QString getStdout();
276 	void setStdoutBuffer(QString *buffer);
277     void setStderrBuffer(QString *buffer);
278 	void setStdoutCodec(QTextCodec *codec);
279 	bool showStderr() const;
280 	void setShowStderr(bool show);
281 	void setOverrideEnvironment(const QStringList &env);
282 	const QStringList &overrideEnvironment();
283 
284 	Q_INVOKABLE int exitStatus() const;
285 	Q_INVOKABLE int exitCode() const;
286 	Q_INVOKABLE QString readAllStandardOutputStr();
287 	Q_INVOKABLE QString readAllStandardErrorStr();
288 	Q_INVOKABLE bool waitForFinished ( int msecs = 30000 );
289 
290 	bool isRunning() const;
291 signals:
292 	void startedX();
293 
294 	void processNotification(const QString &message);
295 	void standardOutputRead(const QString &data);
296 	void standardErrorRead(const QString &data);
297     void processFinished();
298 private slots:
299 	void onStarted();
300 	void onError(QProcess::ProcessError error);
301 	void onFinished(int error);
302 #ifdef PROFILE_PROCESSES
303 	void finished();
304 #endif
305 	void readFromStandardOutput();
306 	void readFromStandardError(bool force = false);
307 private:
308 	friend class BuildManager;
309 	QString cmd;
310 	QString file;
311 	bool isStarted, ended, stderrEnabled, stdoutEnabled, stdoutEnabledOverrideOn;
312     QString *stdoutBuffer,*stderrBuffer;
313 	QTextCodec *stdoutCodec;
314 	QStringList overriddenEnvironment;
315 	QString subCommandName, subCommandPrimary;
316 	RunCommandFlags subCommandFlags;
317 #ifdef PROFILE_PROCESSES
318 	QTime time;
319 #endif
320 };
321 
322 
323 #endif // BUILDMANAGER_H
324