示例#1
0
QTextCursor ScCodeEditor::selectionForPosition( int position )
{
    QTextBlock block( textDocument()->findBlock(position) );
    if (!block.isValid())
        return QTextCursor();

    int positionInBlock = position - block.position();

    TokenIterator it = TokenIterator( block, positionInBlock );
    if (it.type() == Token::Unknown) {
        // Token is invalid, or Token::Unknown (i.e. punctuations).
        // Prefer token at previous position.
        TokenIterator alternativeIt = TokenIterator( block, positionInBlock - 1 );
        if (alternativeIt.isValid())
            it = alternativeIt;
    }

    if (it.isValid()) {
        switch (it->type) {
        case Token::OpeningBracket:
        case Token::ClosingBracket:
        {
            BracketPair match;
            matchBracket(it, match);
            if (match.first.isValid() && match.second.isValid()) {
                int start = match.first.position();
                int end = match.second.position() + 1;
                QTextCursor selection(textDocument());
                if (it == match.second) {
                    selection.setPosition(start);
                    selection.setPosition(end, QTextCursor::KeepAnchor);
                } else {
                    selection.setPosition(end);
                    selection.setPosition(start, QTextCursor::KeepAnchor);
                }
                return selection;
            }
            break;
        }

        default:
            QTextCursor selection( textDocument() );
            selection.setPosition( it.position() );
            selection.setPosition( selection.position() + it->length, QTextCursor::KeepAnchor );
            return selection;
        }
    }

    return QTextCursor();
}
示例#2
0
void ScCodeEditor::matchBrackets()
{
    mBracketSelections.clear();

    QTextCursor cursor(textCursor());
    QTextBlock block( cursor.block() );
    int posInBlock = cursor.positionInBlock();
    TokenIterator it(block);
    while (it.isValid() && it.block() == block)
    {
        const Token & token = *it;
        if (token.positionInBlock > posInBlock) {
            it = TokenIterator();
            break;
        } else if (
            (token.positionInBlock == posInBlock && token.type == Token::OpeningBracket) ||
            (token.positionInBlock == posInBlock - 1 && token.type == Token::ClosingBracket)
        )
            break;
        ++it;
    }

    BracketPair match;
    if( it.isValid() && it.block() == block)
        matchBracket( it, match );

    if( match.first.isValid() && match.second.isValid() )
    {
        const Token & tok1 = *match.first;
        const Token & tok2 = *match.second;

        if (
            (tok1.character == '(' && tok2.character == ')')
            || (tok1.character == '[' && tok2.character == ']')
            || (tok1.character == '{' && tok2.character == '}')
        ){
            QTextEdit::ExtraSelection selection;
            selection.format = mBracketHighlight;
            cursor.setPosition(match.first.position());
            cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
            selection.cursor = cursor;
            mBracketSelections.append(selection);

            cursor.setPosition(match.second.position());
            cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor);
            selection.cursor = cursor;
            mBracketSelections.append(selection);

            if (mHighlightBracketContents) {
                QTextCharFormat format;
                format.setBackground( mBracketHighlight.background() );
                selection.format = format;
                cursor.setPosition(match.first.position()+1);
                cursor.setPosition(match.second.position(), QTextCursor::KeepAnchor);
                selection.cursor = cursor;
                mBracketSelections.append(selection);
            }
        }
        else {
            QTextEdit::ExtraSelection selection;
            selection.format = mBracketMismatchFormat;
            cursor.setPosition(match.first.position());
            cursor.setPosition(match.second.position()+1, QTextCursor::KeepAnchor);
            selection.cursor = cursor;
            mBracketSelections.append(selection);
        }
    }

    updateExtraSelections();
}
示例#3
0
文件: latexparser.cpp 项目: KDE/kile
//FIXME: this has to be completely rewritten!
ParserOutput* LaTeXParser::parse()
{
	LaTeXParserOutput *parserOutput = new LaTeXParserOutput();

	qCDebug(LOG_KILE_PARSER) << m_textLines;

	QMap<QString,KileStructData>::const_iterator it;
	static QRegExp reCommand("(\\\\[a-zA-Z]+)\\s*\\*?\\s*(\\{|\\[)");
	static QRegExp reRoot("\\\\documentclass|\\\\documentstyle");
	static QRegExp reBD("\\\\begin\\s*\\{\\s*document\\s*\\}");
	static QRegExp reReNewCommand("\\\\renewcommand.*$");
	static QRegExp reNumOfParams("\\s*\\[([1-9]+)\\]");
	static QRegExp reNumOfOptParams("\\s*\\[([1-9]+)\\]\\s*\\[([^\\{]*)\\]"); // the quantifier * isn't used by mistake, because also emtpy optional brackets are correct.

	int tagStart, bd = 0;
	int tagEnd, tagLine = 0, tagCol = 0;
	int tagStartLine = 0, tagStartCol = 0;
	BracketResult result;
	QString m, s, shorthand;
	bool foundBD = false; // found \begin { document }
	bool fire = true; //whether or not we should emit a foundItem signal
	bool fireSuspended; // found an item, but it should not be fired (this time)
	TodoResult todo;

// 	emit(parsingStarted(m_doc->lines()));
	for(int i = 0; i < m_textLines.size(); ++i) {
		if(!m_parserThread->shouldContinueDocumentParsing()) {
			qCDebug(LOG_KILE_PARSER) << "stopping...";
			delete(parserOutput);
			return Q_NULLPTR;
		}

//		emit(parsingUpdate(i));

		tagStart = tagEnd = 0;
		fire = true;
		s = processTextline(getTextLine(m_textLines, i), todo);
		if(todo.type != -1 && m_showStructureTodo) {
			QString folder = (todo.type == KileStruct::ToDo) ? "todo" : "fixme";
			parserOutput->structureViewItems.push_back(new StructureViewItem(todo.comment, i+1, todo.colComment, todo.type, KileStruct::Object, i+1, todo.colTag, QString(), folder));
		}


		if(s.isEmpty()) {
			continue;
		}

		//ignore renewcommands
		s.remove(reReNewCommand);

		//find all commands in this line
		while(tagStart != -1) {
			if((!foundBD) && ((bd = s.indexOf(reBD, tagEnd)) != -1)) {
				qCDebug(LOG_KILE_PARSER) << "\tfound \\begin{document}";
				foundBD = true;
				parserOutput->preamble.clear();
//FIXME: improve this
				if(bd == 0) {
					if(i - 1 >= 0) {
						for(int j = 0; j <= i - 1; ++j) {
							parserOutput->preamble += getTextLine(m_textLines, j) + '\n';
						}
					}
				}
				else {
					if(i - 1 >= 0) {
						for(int j = 0; j <= i - 1; ++j) {
							parserOutput->preamble += getTextLine(m_textLines, j) + '\n';
						}
					}
					parserOutput->preamble += getTextLine(m_textLines, i).left(bd) + '\n';
				}
			}

			if((!foundBD) && (s.indexOf(reRoot, tagEnd) != -1)) {
				qCDebug(LOG_KILE_PARSER) << "\tsetting m_bIsRoot to true";
				tagEnd += reRoot.cap(0).length();
				parserOutput->bIsRoot = true;
			}

			tagStart = reCommand.indexIn(s, tagEnd);
			m.clear();
			shorthand.clear();

			if(tagStart != -1) {
				tagEnd = tagStart + reCommand.cap(0).length()-1;

				//look up the command in the dictionary
				it = m_dictStructLevel.constFind(reCommand.cap(1));

				//if it is was a structure element, find the title (or label)
				if(it != m_dictStructLevel.constEnd()) {
					tagLine = i+1;
					tagCol = tagEnd+1;
					tagStartLine = tagLine;
					tagStartCol = tagStart+1;

					if(reCommand.cap(1) != "\\frame") {
						result = matchBracket(m_textLines, i, tagEnd);
						m = result.value.trimmed();
						shorthand = result.option.trimmed();
						if(i >= tagLine) { //matching brackets spanned multiple lines
							s = getTextLine(m_textLines, i);
						}
						if(result.line > 0 || result.col > 0) {
							tagLine = result.line + 1;
							tagCol = result.col + 1;
						}
					//qCDebug(LOG_KILE_PARSER) << "\tgrabbed: " << reCommand.cap(1) << "[" << shorthand << "]{" << m << "}";
					}
					else {
						m = i18n("Frame");
					}
				}

				//title (or label) found, add the element to the listview
				if(!m.isNull()) {
					// no problems so far ...
					fireSuspended = false;

					// remove trailing ./
					if((*it).type & (KileStruct::Input | KileStruct::Graphics)) {
						if(m.left(2) == "./") {
							m = m.mid(2, m.length() - 2);
						}
					}
					// update parameter for environments, because only
					// floating environments and beamer frames are passed
					if ( (*it).type == KileStruct::BeginEnv )
					{
						if ( m=="figure" || m=="figure*" || m=="table" || m=="table*" )
						{
							it = m_dictStructLevel.constFind("\\begin{" + m +'}');
						}
						else if(m == "asy") {
							it = m_dictStructLevel.constFind("\\begin{" + m +'}');
							parserOutput->asyFigures.append(m);
						}
						else if(m == "frame") {
							const QString untitledFrameDisplayName = i18n("Frame");
							it = m_dictStructLevel.constFind("\\begin{frame}");
							if(tagEnd+1 < s.size() && s.at(tagEnd+1) == '{') {
									tagEnd++;
									result = matchBracket(m_textLines, i, tagEnd);
									m = result.value.trimmed();
									if(m.isEmpty()) {
										m = untitledFrameDisplayName;
									}
							}
							else {
								m = untitledFrameDisplayName;
							}
						}
						else if(m=="block" || m=="exampleblock" || m=="alertblock") {
							const QString untitledBlockDisplayName = i18n("Untitled Block");
							it = m_dictStructLevel.constFind("\\begin{block}");
							if(tagEnd+1 < s.size() && s.at(tagEnd+1) == '{') {
								tagEnd++;
								result = matchBracket(m_textLines, i, tagEnd);
								m = result.value.trimmed();
								if(m.isEmpty()) {
									m = untitledBlockDisplayName;
								}
							}
							else {
								m = untitledBlockDisplayName;
							}
						}
						else {
							fireSuspended = true;    // only floats and beamer frames, no other environments
						}
					}

					// tell structure view that a floating environment or a beamer frame must be closed
					else if ( (*it).type == KileStruct::EndEnv )
					{
						if ( m=="figure" || m== "figure*" || m=="table" || m=="table*" || m=="asy")
						{
							it = m_dictStructLevel.constFind("\\end{float}");
						}
						else if(m == "frame") {
							it = m_dictStructLevel.constFind("\\end{frame}");
						}
						else {
							fireSuspended = true;          // only floats, no other environments
						}
					}
					// sectioning commands
					else if((*it).type == KileStruct::Sect) {
						if(!shorthand.isEmpty()) {
							m = shorthand;
						}
					}

					// update the label list
					else if((*it).type == KileStruct::Label) {
						parserOutput->labels.append(m);
						// label entry as child of sectioning
						if(m_showSectioningLabels) {
							parserOutput->structureViewItems.push_back(new StructureViewItem(m, tagLine, tagCol, KileStruct::Label, KileStruct::Object, tagStartLine, tagStartCol, "label", "root"));
							fireSuspended = true;
						}
					}

					// update the references list
					else if((*it).type == KileStruct::Reference) {
						// m_references.append(m);
						//fireSuspended = true;          // don't emit references
					}

					// update the dependencies
					else if((*it).type == KileStruct::Input) {
						// \input- or \include-commands can be used without extension. So we check
						// if an extension exists. If not the default extension is added
						// ( LaTeX reference says that this is '.tex'). This assures that
						// all files, which are listed in the structure view, have an extension.
						QString ext = QFileInfo(m).completeSuffix();
						if(ext.isEmpty()) {
							m += m_extensions->latexDocumentDefault();
						}
						parserOutput->deps.append(m);
					}

					// update the referenced Bib files
					else  if((*it).type == KileStruct::Bibliography) {
						qCDebug(LOG_KILE_PARSER) << "===TeXInfo::updateStruct()===appending Bibiliograph file(s) " << m;

						QStringList bibs = m.split(',');
						QString biblio;

						// assure that all files have an extension
						QString bibext = m_extensions->bibtexDefault();
						int bibextlen = bibext.length();

						uint cumlen = 0;
						int nextbib = 0; // length to add to jump to the next bibliography
						for(int b = 0; b < bibs.count(); ++b) {
							nextbib = 0;
							biblio=bibs[b];
							parserOutput->bibliography.append(biblio);
							if(biblio.left(2) == "./") {
								nextbib += 2;
								biblio = biblio.mid(2, biblio.length() - 2);
							}
							if(biblio.right(bibextlen) != bibext) {
								biblio += bibext;
								nextbib -= bibextlen;
							}
							parserOutput->deps.append(biblio);
							parserOutput->structureViewItems.push_back(new StructureViewItem(biblio, tagLine, tagCol+cumlen, (*it).type, (*it).level, tagStartLine, tagStartCol, (*it).pix, (*it).folder));
							cumlen += biblio.length() + 1 + nextbib;
						}
						fire = false;
					}

					// update the bibitem list
					else if((*it).type == KileStruct::BibItem) {
						//qCDebug(LOG_KILE_PARSER) << "\tappending bibitem " << m;
						parserOutput->bibItems.append(m);
					}

					// update the package list
					else if((*it).type == KileStruct::Package) {
						QStringList pckgs = m.split(',');
						uint cumlen = 0;
						for(int p = 0; p < pckgs.count(); ++p) {
							QString package = pckgs[p].trimmed();
							if(!package.isEmpty()) {
								parserOutput->packages.append(package);
								// hidden, so emit is useless
								// emit( foundItem(package, tagLine, tagCol+cumlen, (*it).type, (*it).level, tagStartLine, tagStartCol, (*it).pix, (*it).folder) );
								cumlen += package.length() + 1;
							}
						}
						fire = false;
					}

					// newcommand found, add it to the newCommands list
					else if((*it).type & (KileStruct::NewCommand | KileStruct::NewEnvironment)) {
						QString optArg, mandArgs;

						//find how many parameters this command takes
						if(s.indexOf(reNumOfParams, tagEnd + 1) != -1) {
							bool ok;
							int noo = reNumOfParams.cap(1).toInt(&ok);

							if(ok) {
								if(s.indexOf(reNumOfOptParams, tagEnd + 1) != -1) {
									qCDebug(LOG_KILE_PARSER) << "Opt param is " << reNumOfOptParams.cap(2) << "%EOL";
									noo--; // if we have an opt argument, we have one mandatory argument less, and noo=0 can't occur because then latex complains (and we don't macht them with reNumOfParams either)
									optArg = '[' + reNumOfOptParams.cap(2) + ']';
								}

								for(int noo_index = 0; noo_index < noo; ++noo_index) {
									mandArgs +=  '{' + s_bullet + '}';
								}

							}
							if(!optArg.isEmpty()) {
								if((*it).type == KileStruct::NewEnvironment) {
									parserOutput->newCommands.append(QString("\\begin{%1}%2%3").arg(m).arg(optArg).arg(mandArgs));
								}
								else {
									parserOutput->newCommands.append(m + optArg + mandArgs);
								}
							}
						}
						if((*it).type == KileStruct::NewEnvironment) {
							parserOutput->newCommands.append(QString("\\begin{%1}%3").arg(m).arg(mandArgs));
							parserOutput->newCommands.append(QString("\\end{%1}").arg(m));
						}
						else {
							parserOutput->newCommands.append(m + mandArgs);
						}
						//FIXME  set tagEnd to the end of the command definition
						break;
					}
					// and some other commands, which don't need special actions:
					// \caption, ...

					// qCDebug(LOG_KILE_PARSER) << "\t\temitting: " << m;
					if(fire && !fireSuspended) {
						parserOutput->structureViewItems.push_back(new StructureViewItem(m, tagLine, tagCol, (*it).type, (*it).level, tagStartLine, tagStartCol, (*it).pix, (*it).folder));
					}
				} //if m
			} // if tagStart
		} // while tagStart
	} //for

	qCDebug(LOG_KILE_PARSER) << "done";
	return parserOutput;
}