int LatexTables::findNextToken(QDocumentCursor &cur,QStringList tokens,bool keepAnchor,bool backwards){ int pos=-1; int nextToken=-1; int offset=0; QDocumentCursor::MoveOperation mvNextLine= backwards ? QDocumentCursor::PreviousLine : QDocumentCursor::NextLine; QDocumentCursor::MoveOperation mvNextChar= backwards ? QDocumentCursor::Left : QDocumentCursor::Right; QDocumentCursor::MoveOperation mvStartOfLine= backwards ? QDocumentCursor::EndOfLine : QDocumentCursor::StartOfLine; QDocumentCursor::MoveFlag mvFlag= keepAnchor ? QDocumentCursor::KeepAnchor : QDocumentCursor::MoveAnchor; do{ QString line=cur.line().text(); if(backwards){ offset=line.length(); } line=LatexParser::cutComment(line); if(backwards){ offset=offset-line.length(); QString help; foreach(const QChar& elem,line) help.prepend(elem); line=help; } if(line.contains("\\end{")&&!backwards) { nextToken=-2; break; } if(line.contains("{nigeb\\")&&backwards) { nextToken=-2; break; } pos=-1; for(int i=0;i<tokens.count();i++){ QString elem=tokens.at(i); int colNumber= cur.columnNumber(); if(backwards) colNumber=line.length()+offset-colNumber ; int zw=line.indexOf(elem,colNumber); if(zw>-1) { if(pos>zw || pos==-1){ pos=zw; nextToken=i; } } } if(pos<0){ if(!backwards&&cur.lineNumber()>=cur.document()->lineCount()-1) break; if(backwards&&cur.lineNumber()<=0) break; cur.movePosition(1,mvNextLine,mvFlag); cur.movePosition(1,mvStartOfLine,mvFlag); } }while(pos<0); if(pos>-1) { cur.movePosition(1,mvStartOfLine,mvFlag); cur.movePosition(pos+tokens.at(nextToken).length()+offset,mvNextChar,mvFlag); } return nextToken; }
void QEditorInputBinding::EditCommand::exec(QEditor *e) { QDocumentCursor c = e->cursor(); switch ( operation ) { case ClearSelection : c.clearSelection(); break; case SelectWord : c.select(QDocumentCursor::WordUnderCursor); break; case SelectLine : c.select(QDocumentCursor::LineUnderCursor); break; case SelectDocument : c.movePosition(1, QDocumentCursor::Start, QDocumentCursor::MoveAnchor); c.movePosition(1, QDocumentCursor::End, QDocumentCursor::KeepAnchor); break; case DeleteChar : c.deleteChar(); break; case DeletePreviousChar : c.deletePreviousChar(); break; case DeleteLine : c.eraseLine(); break; case DeleteSelection : c.removeSelectedText(); break; case InsertLine : c.insertLine(); break; case InsertClipBoard : e->paste(); return; default: break; } e->setCursor(c); }
void simpleRestoreAutoOverride(const QString& written="????"){ //simple means without protecting the change from undo/redo if (!autoOverridenText.isEmpty() && !editor->isAutoOverrideText(written)) { int curpos = editor->cursor().columnNumber(); if (curpos < maxWritten) { QDocumentCursor c = editor->cursor(); c.movePosition(maxWritten-curpos, QDocumentCursor::Right); editor->setCursor(c); } editor->insertText(autoOverridenText); QDocumentCursor c = editor->cursor(); c.movePosition(autoOverridenText.length() + (curpos<maxWritten?maxWritten-curpos:0), QDocumentCursor::Left); editor->setCursor(c); editor->resizeAutoOverridenPlaceholder(c, autoOverridenText.size()); } }
/*! \brief Completion callback */ void QCodeCompletionEngine::complete(const QDocumentCursor& c, const QString& trigger) { #ifdef _QCODE_MODEL_ // TODO : // * use a more efficient design by avoiding deep copy of the data // * only lex the requested part (stop at cursor or topmost frame required for proper class hierarchy) QDocumentCursor cc = c; cc.movePosition(1, QDocumentCursor::Start, QDocumentCursor::KeepAnchor); //qDebug("%s", qPrintable(cc.selectedText())); QCodeBuffer buffer(cc.selectedText()); //QCodeBuffer buffer(c.document()->text()); complete(&buffer, trigger); #else // remove unused argument warnings (void) c; (void) trigger; qWarning("From complete(QDocumentCursor, QString)"); qWarning("QCodeCompletionEngine is not self-sufficient : subclasses should " "reimplement at least on of the complete() method..."); #endif }
/*! \internal */ bool QCodeCompletionEngine::eventFilter(QObject *o, QEvent *e) { if ( !e || !o || (e->type() != QEvent::KeyPress) || (o != pEdit) ) return false; //qDebug("should trigger completion?"); QDocumentCursor cur = editor()->cursor(); QKeyEvent *k = static_cast<QKeyEvent*>(e); QString s, txt = s = k->text(); int count = txt.count(); if ( txt.isEmpty() || m_triggers.isEmpty() ) return false; // QThread::eventFilter(o, e); //qDebug("should trigger completion? (bis)"); if ( count > m_max ) { txt = txt.right(m_max); } else if ( count < m_max ) { QDocumentCursor c(cur); c.movePosition(m_max - count, QDocumentCursor::Left, QDocumentCursor::KeepAnchor); //qDebug("prev text : %s", qPrintable(c.selectedText())); txt.prepend(c.selectedText()); } //qDebug("text : %s", qPrintable(txt)); foreach ( QString trig, m_triggers ) { if ( txt.endsWith(trig) ) { editor()->write(s); cur = editor()->cursor(); cur.movePosition(trig.count(), QDocumentCursor::PreviousCharacter); // notify completion trigger emit completionTriggered(trig); //get rid of previous calltips/completions editor()->setFocus(); // trigger completion complete(cur, trig); return true; } } return false; }
/*! \brief Standard completion entry point for QEditor \param e QKeyEvent that caused a modification of the text \note This slot is only called when editing happens without any cursor mirrors */ void QCodeCompletionEngine::textEdited(QKeyEvent *k) { QString s, txt = s = k->text(); QDocumentCursor cur = editor()->cursor(); int count = txt.count(); if ( txt.isEmpty() || m_triggers.isEmpty() ) return; //qDebug("should trigger completion? (bis)"); if ( count > m_max ) { txt = txt.right(m_max); } else if ( count < m_max ) { QDocumentCursor c(cur); c.movePosition(m_max, QDocumentCursor::Left, QDocumentCursor::KeepAnchor); //qDebug("prev text : %s", qPrintable(c.selectedText())); txt = c.selectedText(); } //qDebug("text : %s", qPrintable(txt)); foreach ( QString trig, m_triggers ) { if ( txt.endsWith(trig) ) { cur = editor()->cursor(); cur.movePosition(trig.count(), QDocumentCursor::PreviousCharacter); // notify completion trigger emit completionTriggered(trig); //get rid of previous calltips/completions editor()->setFocus(); // trigger completion complete(cur, trig); } } }
bool QSnippetBinding::keyPressEvent(QKeyEvent *event, QEditor *editor) { /* if ( event->modifiers() & Qt::ControlModifier ) { for ( int i = 0; i < qMin(10, m->snippetCount()); ++i ) { if ( event->key() == (Qt::Key_F1 + i) ) { m->snippet(i)->insert(editor); return true; } } } */ if ( (event->modifiers() & Qt::AltModifier) && (event->key() == Qt::Key_Space || event->text() == " ") ) { QDocumentCursor c = editor->cursor(); //c.select(QDocumentCursor::SelectWord); if ( !c.hasSelection() ) { c.movePosition(1, QDocumentCursor::PreviousWord, QDocumentCursor::KeepAnchor); editor->setCursor(c); } QString s = c.selectedText(); for ( int i = 0; i < m_manager->snippetCount(); ++i ) { QSnippet *snip = m_manager->snippet(i); if ( snip->name() == s ) { snip->insert(editor); return true; } } } return QEditorInputBinding::keyPressEvent(event, editor); }
QString LatexTables::getDef(QDocumentCursor &cur){ QDocumentCursor c(cur); int result=findNextToken(c,QStringList(),false,true); if(result!=-2) return QString(); QString line=c.line().text(); QString opt; int pos=line.indexOf("\\begin"); if(pos>-1){ QStringList values; QList<int> starts; LatexParser::resolveCommandOptions(line,pos,values,&starts); QString env=values.takeFirst(); pos=starts.takeFirst(); if(!env.startsWith("{")||!env.endsWith("}")) return QString(); env=env.mid(1); env.chop(1); int numberOfOptions=-1; if(tabularNames.contains(env)) numberOfOptions=0; if(tabularNamesWithOneOption.contains(env)) numberOfOptions=1; if(numberOfOptions>=0){ while(!values.isEmpty()){ opt=values.takeFirst(); pos=starts.takeFirst(); if(opt.startsWith("[")&&opt.endsWith("]")) continue; if(numberOfOptions>0) { numberOfOptions--; continue; } if(!opt.startsWith("{")||!opt.endsWith("}")) return QString(); opt=opt.mid(1); opt.chop(1); cur.moveTo(c.line(),pos+1); cur.movePosition(opt.length(),QDocumentCursor::NextCharacter,QDocumentCursor::KeepAnchor); } } } return opt; }
void CodeSnippet::insertAt(QEditor* editor, QDocumentCursor* cursor, bool usePlaceholders, bool byCompleter) const{ if (lines.empty()||!editor||!cursor) return; //find filechooser escape %( %) QString line=lines.join("\n"); QRegExp rx("%\\((.+)%\\)"); int pos=rx.indexIn(line,0); if(pos>-1){ FileChooser sfDlg(0,QApplication::tr("Select a File")); sfDlg.setFilter(rx.cap(1)); LatexDocument *doc=qobject_cast<LatexDocument*>(cursor->document()); QString path=doc->parent->getCompileFileName(); path=getPathfromFilename(path); QString directory; if(path.isEmpty()) directory=QDir::homePath(); else directory=path; sfDlg.setDir(directory); if (sfDlg.exec()) { QString fn=sfDlg.fileName(); line.replace(rx,getRelativeBaseNameToPath(fn,path)); } else return; } QString savedSelection; bool alwaysSelect = false; bool editBlockOpened = false; if (cursor->hasSelection()) { savedSelection=cursor->selectedText(); editBlockOpened = true; cursor->beginEditBlock(); cursor->removeSelectedText(); }else if(!editor->cutBuffer.isEmpty()){ savedSelection=editor->cutBuffer; editor->cutBuffer.clear(); alwaysSelect = true; } bool multiLineSavedSelection = savedSelection.contains("\n"); QDocumentCursor selector=*cursor; QDocumentLine curLine=cursor->line(); // on multi line commands, replace environments only if(autoReplaceCommands && lines.size()>1 && line.contains("\\begin{")){ QString curLine=cursor->line().text(); int wordBreak=curLine.indexOf(QRegExp("\\W"),cursor->columnNumber()); int closeCurl=curLine.indexOf("}",cursor->columnNumber()); int openCurl=curLine.indexOf("{",cursor->columnNumber()); int openBracket=curLine.indexOf("[",cursor->columnNumber()); if(closeCurl>0){ if(openBracket<0) openBracket=1e9; if(openCurl<0) openCurl=1e9; if(wordBreak<0) wordBreak=1e9; if(closeCurl<openBracket && (closeCurl<=wordBreak || openCurl<=wordBreak)){ QString oldEnv; if(closeCurl<openCurl) oldEnv=curLine.mid(cursor->columnNumber(),closeCurl-cursor->columnNumber()); else oldEnv=curLine.mid(openCurl+1,closeCurl-openCurl-1); QRegExp rx("\\\\begin\\{(.+)\\}"); rx.setMinimal(true); rx.indexIn(line); QString newEnv=rx.cap(1); // remove curly brakets as well QDocument* doc=cursor->document(); QString searchWord="\\end{"+oldEnv+"}"; QString inhibitor="\\begin{"+oldEnv+"}"; bool backward=false; int step=1; int startLine=cursor->lineNumber(); //int startCol=cursor.columnNumber(); int endLine=doc->findLineContaining(searchWord,startLine+step,Qt::CaseSensitive,backward); int inhibitLine=doc->findLineContaining(inhibitor,startLine+step,Qt::CaseSensitive,backward); // not perfect (same line end/start ...) while (inhibitLine>0 && endLine>0 && inhibitLine*step<endLine*step) { endLine=doc->findLineContaining(searchWord,endLine+step,Qt::CaseSensitive,backward); // not perfect (same line end/start ...) inhibitLine=doc->findLineContaining(inhibitor,inhibitLine+step,Qt::CaseSensitive,backward); } QString endText=doc->line(endLine).text(); int start=endText.indexOf(searchWord); int offset=searchWord.indexOf("{"); int length=searchWord.length()-offset-1; selector.moveTo(endLine,start+1+offset); selector.movePosition(length-1,QDocumentCursor::Right,QDocumentCursor::KeepAnchor); selector.replaceSelectedText(newEnv); cursor->movePosition(closeCurl-cursor->columnNumber()+1,QDocumentCursor::Right,QDocumentCursor::KeepAnchor); QString first=lines.first(); int pos=first.indexOf('{'); pos=first.indexOf('{',pos+1); //pos of second { if(pos>-1) first.remove(pos,first.length()-pos); editor->insertText(*cursor,first); if (editBlockOpened) cursor->endEditBlock(); return; } } } int baseLine=cursor->lineNumber(); int baseLineIndent = cursor->columnNumber(); //text before inserted word moves placeholders to the right int lastLineRemainingLength = curLine.text().length()-baseLineIndent; //last line will has length: indentation + codesnippet + lastLineRemainingLength editor->insertText(*cursor,line); //don't use cursor->insertText to keep autoindentation working if (editBlockOpened) cursor->endEditBlock(); // on single line commands only: replace command if(byCompleter && autoReplaceCommands && lines.size()==1 && line.startsWith('\\')){ if(cursor->nextChar().isLetterOrNumber()||cursor->nextChar()==QChar('{')){ QString curLine=cursor->line().text(); int wordBreak=curLine.indexOf(QRegExp("\\W"),cursor->columnNumber()); int closeCurl=curLine.indexOf("}",cursor->columnNumber()); int openCurl=curLine.indexOf("{",cursor->columnNumber()); int openBracket=curLine.indexOf("[",cursor->columnNumber()); if(!line.contains("{")){ if(openBracket<0) openBracket=1e9; if(closeCurl<0) closeCurl=1e9; if(openCurl<0) openCurl=1e9; if(wordBreak<openBracket && wordBreak<closeCurl &&wordBreak<openCurl){ if(wordBreak<0) cursor->movePosition(wordBreak-cursor->columnNumber(),QDocumentCursor::EndOfLine,QDocumentCursor::KeepAnchor); else cursor->movePosition(wordBreak-cursor->columnNumber(),QDocumentCursor::Right,QDocumentCursor::KeepAnchor); cursor->removeSelectedText(); return; } }else{ if(openCurl>-1){ if(openBracket<0) openBracket=1e9; if(closeCurl<0) closeCurl=1e9; if(openCurl<openBracket && openCurl<closeCurl &&openCurl<=wordBreak){ cursor->movePosition(openCurl-cursor->columnNumber(),QDocumentCursor::Right,QDocumentCursor::KeepAnchor); cursor->removeSelectedText(); int curl=line.length()-line.indexOf("{"); cursor->movePosition(curl,QDocumentCursor::Left,QDocumentCursor::KeepAnchor); cursor->removeSelectedText(); return; } } } } } Q_ASSERT(placeHolders.size()==lines.count()); if (usePlaceholders) { //check if there actually are placeholders to insert usePlaceholders=false; for (int l=0;l< lines.count();l++) usePlaceholders|=placeHolders[l].size(); } int autoSelectPlaceholder = -1; if (usePlaceholders) { if (editor->currentPlaceHolder()!=-1 && editor->getPlaceHolder(editor->currentPlaceHolder()).cursor.isWithinSelection(*cursor)) editor->removePlaceHolder(editor->currentPlaceHolder()); //remove currentplaceholder to prevent nesting for (int l=0;l< lines.count();l++){ //if (l<mLines.count()-1) cursor->insertLine(); for (int i=0; i<placeHolders[l].size(); i++) { if (placeHolders[l][i].flags & CodeSnippetPlaceHolder::Mirror) continue; PlaceHolder ph; ph.length=placeHolders[l][i].length; ph.cursor = getCursor(editor, placeHolders[l][i], l, baseLine, baseLineIndent, lastLineRemainingLength); ph.autoRemove = !(placeHolders[l][i].flags & CodeSnippetPlaceHolder::Persistent); if (!ph.cursor.isValid()) continue; editor->addPlaceHolder(ph); if (placeHolders[l][i].flags & CodeSnippetPlaceHolder::Mirrored) { int phId = editor->placeHolderCount()-1; for (int lm=0; lm<placeHolders.size(); lm++) for (int im=0; im < placeHolders[lm].size(); im++) if (placeHolders[lm][im].flags & CodeSnippetPlaceHolder::Mirror && placeHolders[lm][im].id == placeHolders[l][i].id) editor->addPlaceHolderMirror(phId, getCursor(editor, placeHolders[lm][im], lm, baseLine, baseLineIndent, lastLineRemainingLength)); } if ((placeHolders[l][i].flags & CodeSnippetPlaceHolder::AutoSelect) && ((autoSelectPlaceholder == -1) || (multiLineSavedSelection && (placeHolders[l][i].flags & CodeSnippetPlaceHolder::PreferredMultilineAutoSelect)))) autoSelectPlaceholder = editor->placeHolderCount()-1; } } } //place cursor/add \end if (cursorOffset!=-1) { int realAnchorOffset=anchorOffset; //will be moved to the right if text is already inserted on this line if (cursorLine>0) { if (cursorLine>=lines.size()) return; if (!selector.movePosition(cursorLine,QDocumentCursor::Down,QDocumentCursor::MoveAnchor)) return; //if (editor->flag(QEditor::AutoIndent)) realAnchorOffset += selector.line().length()-lines[cursorLine].length(); if (cursorLine + 1 == lines.size()) realAnchorOffset-=lastLineRemainingLength; } else realAnchorOffset += baseLineIndent; selector.setColumnNumber(realAnchorOffset); bool ok=true; if (cursorOffset>anchorOffset) ok=selector.movePosition(cursorOffset-anchorOffset,QDocumentCursor::Right,QDocumentCursor::KeepAnchor); else if (cursorOffset<anchorOffset) ok=selector.movePosition(anchorOffset-cursorOffset,QDocumentCursor::Left,QDocumentCursor::KeepAnchor); if (!ok) return; editor->setCursor(selector); } else if (autoSelectPlaceholder!=-1) editor->setPlaceHolder(autoSelectPlaceholder, true); //this moves the cursor to that placeholder else { editor->setCursor(*cursor); //place after insertion return; } if (!savedSelection.isEmpty()) { QDocumentCursor oldCursor = editor->cursor(); editor->cursor().insertText(savedSelection,true); if (!editor->cursor().hasSelection() && alwaysSelect) { oldCursor.movePosition(savedSelection.length(), QDocumentCursor::Right, QDocumentCursor::KeepAnchor); editor->setCursor(oldCursor); } if (autoSelectPlaceholder!=-1) editor->setPlaceHolder(autoSelectPlaceholder, true); //this synchronizes the placeholder mirrors with the current placeholder text } }
void QEditorInputBinding::MotionCommand::exec(QEditor *e) { QDocumentCursor c = e->cursor(); c.movePosition(count, operation, mode); e->setCursor(c); }