File: smallUsefulFunctions.h

package info (click to toggle)
texstudio 2.11.2%2Bdebian-1
  • links: PTS
  • area: main
  • in suites: stretch
  • size: 41,292 kB
  • ctags: 12,405
  • sloc: cpp: 93,072; xml: 10,217; ansic: 4,153; sh: 145; makefile: 56
file content (437 lines) | stat: -rw-r--r-- 20,151 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
/***************************************************************************
 *   copyright       : (C) 2008 by Benito van der Zander                   *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef SMALLUSEFULFUNCTIONS_H
#define SMALLUSEFULFUNCTIONS_H

#include "mostQtHeaders.h"
#include "qglobal.h"

/*! \file smallUsefulFunctions.h
 * Defines helper functions for various purposes
 * - helper functions for latex parsing
 * - helper functions for character substitution
 * - helper functions for setting-up commandlist to interpret commands
 */

// subgroups of utility functions:
#include "utilsUI.h"
#include "utilsSystem.h"
#include "utilsVersion.h"

#include "codesnippet.h"
//#inlcude "latexcompleter_config.h"

// evaluates to j if i < 0
//              i if j < 0
//              qMin(i, j) if i, j >= 0
// Usage example:
// find the first occuence of either A or B in a string
// pos = indexMin(s.indexOf('A'), s.indexOf('B'))
// pos is negative if s does not contain neither A nor B
#define indexMin(i, j) ((i < 0) ? qMax(i, j) : (j < 0) ? qMax(i, j) : qMin(i, j))


struct CommandArgument {
	bool isOptional;
	int number;
	QString value;
};
Q_DECLARE_METATYPE( CommandArgument )

//void txs_assert(const char *assertion, const char *file, int line);
class QDocumentLineHandle;
class QDocument;


class LatexCompleterConfig;
/*!
 * \brief repesent syntax information on text element
 * The objective for this class is to translate a text(-line) into a series of tokens which can be interpreted much faster and easier subsequently
 * The translation process is divided into 2 passes.
 *
 * Pass 1 simply determines word limits and symbols
 * e.g.\n
 * \\label{abc} def\n
 * is translated to
 \verbatim
 [command 0 6] [openBrace 7 1] [word 8 3] [closeBrace 12 1] [word 14 3]
 \endverbatim
 *
 * no context is used
 *
 * Pass 2 interprets the data in order to assign arguments to commands and to assign a purpose for the arguments if they are defined in the cwl
 * It uses the tokens from the first pass to speed-up processing\n
 * e.g. (from previous example, level is represented by the line, type/subtype is given)\n
 \verbatim
 level=0 [command/none 0 6] [braces/label 7 5]                  [word/none 14 3]
 level=1                                       [label/none 8 3]
 \endverbatim
 The level is encoded via the level-property. The list is actually still linear.
 */
class Tokens
{
public:
	Tokens(): start(-1), length(-1), level(-1), dlh(0), type(none), subtype(none), argLevel(0) {}
	int start;
	int length;
	int level;
    QString optionalCommandName;
	QDocumentLineHandle *dlh;

	enum TokenType {none = 0, word, command, braces, bracket,
	                squareBracket, openBrace, openBracket, openSquare, closeBrace,
	                closeBracket, closeSquareBracket, math, comment, commandUnknown, label, bibItem, file, imagefile, bibfile,
	                keyValArg, keyVal_key, keyVal_val, list, text, env, beginEnv, def, labelRef, package, width, placement, colDef, title, url, documentclass, beamertheme, packageoption,
	                color, verbatimStart, verbatimStop, verbatim, symbol, punctuation, number, generalArg, defArgNumber, optionalArgDefinition, definition, defWidth, labelRefList, specialArg, newTheorem,newBibItem,_end = 255
	               };
	static QString tokenTypeName(TokenType t);

	TokenType type;
	/// subtype is used to determine the type of argument
	TokenType subtype;
	int argLevel; ///< number of argument (>0) or option (<0, =-numberOfOption)
	static QSet<TokenType> tkArg();
	static QSet<TokenType> tkOption();
	static QSet<TokenType> tkBraces();
	static QSet<TokenType> tkOpen();
	static QSet<TokenType> tkClose();
	static QSet<TokenType> tkCommalist();
	static QSet<TokenType> tkSingleArg();
	static TokenType opposite(TokenType type);
	static TokenType closed(TokenType type);
	bool operator==(const Tokens &v) const;
	QString getText();
};
QDebug operator<<(QDebug dbg, Tokens::TokenType tk);
QDebug operator<<(QDebug dbg, Tokens tk);

typedef QList<Tokens> TokenList;
typedef QStack<Tokens> TokenStack;

Q_DECLARE_METATYPE(TokenList);
Q_DECLARE_METATYPE(TokenStack);
void qDebugTokenList(TokenList tl);

/*!
 * \brief define available arguments for a command
 */
class CommandDescription
{
public:
	CommandDescription();
	int optionalArgs; ///< number of optional arguments
	int bracketArgs; ///< number of () arguments
	int args; ///< number of mandatory arguments (in braces)
	int level;
	QList<Tokens::TokenType> argTypes; ///< define argument type as token
	QList<Tokens::TokenType> optTypes; ///< define argument type as token
	QList<Tokens::TokenType> bracketTypes; ///< define argument type as token
    QString optionalCommandName; ///< stores optionally command name. It is used for processing command description during lexing
	QString toDebugString() const; ///< debug function to get easier information on command description
    bool operator==(const CommandDescription &v) const; ///< compare two command descriptions
};

typedef QStack<CommandDescription> CommandStack;

Q_DECLARE_METATYPE(CommandStack);

typedef QHash<QString, CommandDescription> CommandDescriptionHash;

typedef QString (QObject::*StringToStringCallback)(const QString &) ;

QString getCommonEOW();


/// removes special latex characters
QString latexToPlainWord(const QString &word);
QString latexToPlainWordwithReplacementList(const QString &word, QMap<QString, QString> &replacementList );
/// closing bracket (opening and closing bracket considered correctly)
int findClosingBracket(const QString &word, int &start, QChar oc = QChar('{'), QChar cc = QChar('}'));
/// opening bracket (opening and closing bracket considered correctly), start at "start"
int findOpeningBracket(const QString &word, int start, QChar oc = QChar('{'), QChar cc = QChar('}'));
/// replaces character with corresponding LaTeX commands
QString textToLatex(const QString &text);
QString latexToText(QString s);

QStringList joinLinesExceptCommentsAndEmptyLines(const QStringList &lines);
QStringList splitLines(const QStringList &lines, int maxCharPerLine, const QRegExp &breakChars);

/// compares two strings locale aware
bool localeAwareLessThan(const QString &s1, const QString &s2);

/// true for characters that are valid in latex command names, e.g. \section*
inline bool isCommandChar(const QChar &c)
{
	return c.isLetter() || c == '*';
}
/// returns the position of the first non-whitespace at or after pos
int getCommand(const QString &line, QString &outCmd, int pos = 0);
QList< CommandArgument > getCommandOptions(const QString &line, int pos = 0, int *posBehind = 0);
QString getParamItem(const QString &line, int pos, bool stopAtWhiteSpace = false);

QString trimLeft(const QString &s);
QString trimRight(const QString &s);

/// find token (e.g. \label \input \section and return content (\section{content})
QString findToken(const QString &line, const QString &token);
QString findToken(const QString &line, const QString &token, int &start);
QString findToken(const QString &line, QRegExp &token);
/// find token (e.g. \label \input \section and return content (\newcommand{name}[arg]), returns true if outName!=""
bool findTokenWithArg(const QString &line, const QString &token, QString &outName, QString &outArg);
int findCommandWithArgs(const QString &line, QString &cmd, QStringList &args, QList<int> *argStarts = 0, int offset = 0, bool parseComment = false);
int findCommandWithArgsFromTL(const TokenList &tl, Tokens &cmd, TokenList &args, int offset, bool parseComment = false);


/// generate multiple times used regexpression
QRegExp generateRegExp(const QString &text, const bool isCase, const bool isWord, const bool isRegExp);

QStringList regExpFindAllMatches(const QString &searchIn, const QRegExp &regexp, int cap = 0);
QList<int> indicesOf(const QString &line, const QString &word, Qt::CaseSensitivity cs = Qt::CaseSensitive);
QList<int> indicesOf(const QString &line, const QRegExp &rx);

/// add Environment to QNFA DOM
void addEnvironmentToDom(QDomDocument &doc, const QString &EnvironName, const QString &EnvironMode, bool completeParentheses=true);
void addStructureCommandsToDom(QDomDocument &doc , const QHash<QString, QSet<QString> > &possibleCommands);

QString intListToStr(const QList<int> &ints);
QList<int> strToIntList(const QString &s);

bool minimalJsonParse(const QString &text, QHash<QString, QString> &map);
/// generates a string in the format "id"  : "val", where the colon is at least a position minIdWidth+2 (filling with spaces)
QString formatJsonStringParam(const QString &id, const QString &val, int minIdWidth = 0);
QString enquoteStr(const QString &s);
QString dequoteStr(const QString &s);

QString quotePath(const QString &s);
QString removeQuote(const QString &s);
QString removePathDelim(const QString &s);
QString removeAccents(const QString &s);
QString makeLatexLabel(const QString &s);

uint joinUnicodeSurrogate(const QChar &highSurrogate, const QChar &lowSurrogate);

QTextCodec *guessEncodingBasic(const QByteArray &data, int *outSure);

enum {
	MIB_LATIN1 = 4,
	MIB_WINDOWS1252 = 2252,
	MIB_UTF8 = 106,
	MIB_UTF16BE = 1013,
	MIB_UTF16LE = 1014

};
/*! encode image as text for html
 * This is used to generate images for tooltips.
 */
QString getImageAsText(const QPixmap &AImage, const int w = -1);
void showTooltipLimited(QPoint pos, QString text, int relatedWidgetWidth = 0);
QString truncateLines(const QString &s, int maxLines);

bool addMostRecent(const QString &item, QStringList &mostRecentList, int maxLength);

/*!
 * \brief The ArgumentList class holds lists of LaTeX command arguments
 *
 * An argument is enclosed either in curly or square brackets (mandatory/optional argument).
 */
class ArgumentList : public QStringList
{
public:
	inline ArgumentList() {}
	enum ArgType {Optional, Mandatory};
	QString argContent(int index) const;
	QString argContent(int index, ArgType type) const;
	ArgType argType(int index) const;
	int count(ArgType type) const;
};
/*!
 * \brief class for storing latex syntax informtion and latex parsing
 *
 * The latex parsing is less important since the token based system, but the storage of syntax information is still used.
 */
class LatexParser
{
	friend class SmallUsefulFunctionsTest;
public:
	LatexParser(); ///< constructor
	~LatexParser();
	void init(); ///< set default values

	static const int MAX_STRUCTURE_LEVEL;
	
	enum ContextType {Unknown, Command, Environment, Label, Reference, Citation, Citation_Ext, Option, Graphics, Package, Keyval, KeyvalValue, OptionEx, ArgEx};
	// could do with some generalization as well, optionEx/argEx -> special treatment with specialOptionCommands

	/// realizes whether col is in a \command or in a parameter {}
	int findContext(QString &line, int &column) const;

	///position of the % starting a comment (takes care of multiple backslashes before comment character ..)
	static int commentStart(const QString &text);

	/// remove comment from text, take care of multiple backslashes before comment character ...
	static QString cutComment(const QString &text);

	ContextType findContext(const QString &line, int column, QString &command, QString &value) const;
	static bool resolveCommandOptions(const QString &line, int column, QStringList &values, QList<int> *starts = 0);
	static QString removeOptionBrackets(const QString &option);

	QSet<QString> environmentCommands; ///< used by LatexReader only, obsolete
	QSet<QString> optionCommands; ///< used by LatexReader only, obsolete
	QStringList mathStartCommands; ///< commands to start math-mode like '$'
	QStringList mathStopCommands; ///< commands to stop math-mode like '$'
	QSet<QString> customCommands; ///< commands defined in config dialog as custom commands
	int structureDepth()
	{
		return MAX_STRUCTURE_LEVEL;
	}
	int structureCommandLevel(const QString &cmd) const;
	QMultiHash<QString, QString> packageAliases; ///< aliases for classes to packages e.g. article = latex-document, latex-mathsymbols, etc
	QMultiHash<QString, QString> environmentAliases; ///< aliases for environments, e.g. equation is math, supertabular is also tab etc.
	/// commands used for syntax check (per doc basis)
	QHash<QString, QSet<QString> > possibleCommands;
	QHash<QString, QSet<QPair<QString, int> > > specialTreatmentCommands; ///< special commands, obsolete
	QHash<QString, QString> specialDefCommands; ///< define special elements, e.g. define color etc
	QMap<int, QString> mapSpecialArgs;

	CommandDescriptionHash commandDefs; ///< command definitions

	void append(const LatexParser &elem); ///< append values
	void substract(const LatexParser &elem); ///< remove values
	void importCwlAliases(); ///< import package aliases from disc
	void clear(); ///< set to default values
	static QTextCodec *QTextCodecForLatexName(QString str); ///< get textcodec from codec name
	static QStringList latexNamesForTextCodec(const QTextCodec *codec); ///< get codec name used in latex from text codec
	static void guessEncoding(const QByteArray &data, QTextCodec *&guess, int &sure); ///< guess text codec for file

	static LatexParser &getInstance();
private:
	static int lineStart(const QByteArray &data, int index);
	static int lineEnd(const QByteArray &data, int index);
	static QString getEncodingFromPackage(const QByteArray &data, int headerSize, const QString &packageName); ///< get encoding from usepackage definition in file
};

Q_DECLARE_METATYPE(LatexParser)
/*!
 * \brief class for parsing latex code
 *
 * \warning obsolete with lexer based token system
 * \note this functionality is still used in none-core methods
 */
struct LatexReader {
	LatexReader();
	LatexReader(const QString &line);
	LatexReader(const LatexParser &lp, const QString &line);
	LatexReader(const LatexParser &lp, const QString &line, QMap<QString, QString> &replacementList);

	/*! searches the next token in the line line after/at the index index
	 there are these possible kind of tokens % (which starts a comment), { or } (as parentheses), \.* (command) or .* (text)
	 \param index returns the index of the first character after the word
	 \param inOption Don't stop at eow characters
	 \param detectMath If true, returns $ $$ _ ^ & as commands
	 \returns start index of the token (or -1 if last)
	*/
	static int nextToken(const QString &line, int &index, bool inOption, bool detectMath);

	enum NextWordFlag {
		NW_NOTHING = 0,
		NW_TEXT = 1,
		NW_COMMAND = 2,
		NW_COMMENT = 3,
		NW_ENVIRONMENT = 4, ///< environment name, e.g. in \begin or \newenvironment
		NW_REFERENCE = 5,
		NW_LABEL = 6,
		NW_CITATION = 7,
		NW_PUNCTATION = 8,
		NW_PACKAGE = 9
	};

	//Returns the next word (giving meaning to the nextToken tokens)
	//line: line to be examined
	//index: start index as input and returns the first character after the found word
	//outWord: found word (length can differ from index - wordStartIndex for text words)
	//wordStartIndex: start of the word
	//returnCommands: if this is true it returns \commands (NW_COMMAND), "normal" "text"  NW_TEXT and % (NW_COMMENT)  [or NW_NOTHING at the end]
	//                "    "  is false it only returns normal text (NW_TEXT, without things like filenames after \include), environment names
	//                          (NW_ENVIRONMENT, they are treated as text in the other mode) and % (NW_COMMENT)       [or NW_NOTHING at the end]
	//returns the type of outWord
	NextWordFlag nextWord(bool returnCommands);

	//searches the next text words and ignores command options, environments or comments
	//returns false if none is found
	bool nextTextWord();

	const QString &getLine() const; ///< get current line of latexParser
	void setLine(const QString &line); ///< set line for latexParser
	QString line; ///< current line used in latexParser

	int index; ///< current used column position
	QString word; ///< currently handled word
	QString lastCommand; ///< currently active command
	int wordStartIndex; ///< index of \a word

private:
	const LatexParser *lp;
	QMap<QString, QString> mReplacementList;
};


typedef QPair<QString, int> QPairQStringInt;
/*!
 * \brief store necessary information for latex package
 *
 * Stores commands for completion and syntax check.
 */
class LatexPackage
{
public:
	LatexPackage();

	// Temporary solution: keys of LatexDocuments::cachedPackages have become complex. Use these functions to manage them.
	// This is a first step for refactoring the existing code. No functionality is changed.
	// In the long run, the information should be stored and accessed via the LatexPackage objects, which are referenced by the keys.
	static QString makeKey(const QString &cwlFilename, const QString &options);  // TODO not yet used: where are the keys actually created?
	static QString keyToCwlFilename(const QString &key);
	static QString keyToPackageName(const QString &key);
	static QStringList keyToOptions(const QString &key);

	bool notFound;  // Workaround: explicit flag better than using a magic value in package name. TODO: Do we need not found packages?
	QString packageName; ///< name of package
	QStringList requiredPackages; ///< necessary sub-packages
	CodeSnippetList completionWords; ///< list of completion words
	QHash<QString, QSet<QString> > possibleCommands; ///< possible commands, info for syntax checking
	QHash<QString, QString> specialDefCommands; ///< define special elements, e.g. define color etc
	QSet<QString> optionCommands; ///< commands which contain arguments, obsolete
	QHash<QString, QSet< QPairQStringInt > > specialTreatmentCommands; ///< special commands, obsolete
	QMultiHash<QString, QString> environmentAliases; ///< environment aliases, especially environments which signify math environments concerning syntax check
	CommandDescriptionHash commandDescriptions; ///< command definitions
	void unite(LatexPackage &add, bool forCompletion = false); ///< merge with LatexPackage \a add
};

LatexPackage loadCwlFile(const QString fileName, LatexCompleterConfig *config = 0, QStringList conditions = QStringList());

class QDocumentLineHandle;

QString getArg(TokenList tl, QDocumentLineHandle *dlh, int argNumber, ArgumentList::ArgType type);
QString getArg(const TokenList &tl,Tokens::TokenType type);
QString findRestArg(QDocumentLineHandle *dlh, Tokens::TokenType type, int count = 10);
CommandDescription extractCommandDef(QString line, QString definition);
CommandDescription extractCommandDefKeyVal(QString line, QString &key);
Tokens getTokenAtCol(QDocumentLineHandle *dlh, int pos, bool first = false);
int getTokenAtCol(TokenList &tl, int pos, bool first = false);
TokenList getArgContent(Tokens &tk);
TokenList getArgContent(TokenList &tl, int pos, int level, int runAwayPrevention = 10);
TokenStack getContext(QDocumentLineHandle *dlh, int pos);
QString getCommandFromToken(Tokens tk); ///< get command name from Token \a tk which is an argument
Tokens getCommandTokenFromToken(TokenList tl, Tokens tk);
TokenList simpleLexLatexLine(QDocumentLineHandle *dlh); ///< first pass lexing of text line
bool latexDetermineContexts2(QDocumentLineHandle *dlh, TokenStack &stack, CommandStack &commandStack, const LatexParser &lp); ///< second pass lexing of text line, uses tokens from first pass
int getCompleterContext(QDocumentLineHandle *dlh, int column);
#endif