QString Help::getKeyword(KTextEditor::View *view) { if(!view) { return QString(); } // get current position int row, col, col1, col2; QString word; KTextEditor::Document *doc = view->document(); KTextEditor::Cursor cursor = view->cursorPosition(); row = cursor.line(); col = cursor.column(); if (m_edit->getCurrentWord(doc, row, col, KileDocument::EditorExtension::smTex, word, col1, col2)) { // There is no starred keyword in the references. So if // dani 04.08.2004 // we find one, we better try the unstarred keyword. if(word.right(1) == "*") { return word.left(word.length() - 1); } else { return word; } } else { return QString(); } }
KTextEditor::Range IncludeHelperCompletionModel::completionRange( KTextEditor::View* view , const KTextEditor::Cursor& position ) { kDebug(DEBUG_AREA) << "cursor: " << position; auto line = view->document()->line(position.line()); auto r = parseIncludeDirective(line, false); if (r.m_range.isValid()) { auto start = line.lastIndexOf('/', r.m_range.end().column() - 1); kDebug(DEBUG_AREA) << "init start=" << start; start = start == -1 ? r.m_range.start().column() : start + 1; kDebug(DEBUG_AREA) << "fixed start=" << start; KTextEditor::Range range( position.line() , start , position.line() , r.m_range.end().column() ); kDebug(DEBUG_AREA) << "selected range: " << range; return range; } kDebug(DEBUG_AREA) << "default select"; #if 0 return KTextEditor::Range(); #else return KTextEditor::CodeCompletionModelControllerInterface3::completionRange(view, position); #endif }
bool PythonCodeCompletionModel::shouldStartCompletion(KTextEditor::View* view, const QString& inserted, bool userInsertion, const KTextEditor::Cursor& position) { QList<QString> words; words << "for" << "raise" << "except" << "in"; foreach ( const QString& word, words ) { if ( view->document()->line(position.line()).mid(0, position.column()).endsWith(word + " ") ) { return true; } } // shebang / encoding lines if ( view->document()->line(position.line()).mid(0, position.column()).endsWith("#") && position.line() < 2 ) { return true; } // we're probably dealing with string formatting completion // is there any other case where this condition is true? if ( ! userInsertion && inserted.startsWith('{') ) { return true; } return KDevelop::CodeCompletionModel::shouldStartCompletion(view, inserted, userInsertion, position); }
void TextBuffer::wrapLine (const KTextEditor::Cursor &position) { // only allowed if editing transaction running Q_ASSERT (m_editingTransactions > 0); // get block, this will assert on invalid line int blockIndex = blockForLine (position.line()); // let the block handle the wrapLine // this can only lead to one more line in this block // no other blocks will change ++m_lines; // first alter the line counter, as functions called will need the valid one m_blocks.at(blockIndex)->wrapLine (position); // remember changes ++m_revision; // update changed line interval if (position.line() < m_editingMinimalLineChanged || m_editingMinimalLineChanged == -1) m_editingMinimalLineChanged = position.line(); if (position.line() <= m_editingMaximalLineChanged) ++m_editingMaximalLineChanged; else m_editingMaximalLineChanged = position.line() + 1; // fixup all following blocks fixStartLines (blockIndex); // balance the changed block if needed balanceBlock (blockIndex); // emit signal about done change emit lineWrapped (position); }
void TextBuffer::insertText (const KTextEditor::Cursor &position, const QString &text) { // only allowed if editing transaction running Q_ASSERT (m_editingTransactions > 0); // skip work, if no text to insert if (text.isEmpty()) return; // get block, this will assert on invalid line int blockIndex = blockForLine (position.line()); // let the block handle the insertText m_blocks.at(blockIndex)->insertText (position, text); // remember changes ++m_revision; // update changed line interval if (position.line () < m_editingMinimalLineChanged || m_editingMinimalLineChanged == -1) m_editingMinimalLineChanged = position.line (); if (position.line () > m_editingMaximalLineChanged) m_editingMaximalLineChanged = position.line (); // emit signal about done change emit textInserted (position, text); }
void KateAutoIndent::scriptIndent (KateView *view, const KTextEditor::Cursor &position, QChar typedChar) { QPair<int, int> result = m_script->indent (view, position, typedChar, indentWidth); int newIndentInChars = result.first; // handle negative values special if (newIndentInChars < -1) return; // reuse indentation of the previous line, just like the "normal" indenter if (newIndentInChars == -1) { // keep indent of previous line keepIndent (position.line()); return; } int align = result.second; if (align > 0) kDebug (13060) << "Align: " << align; // we got a positive or zero indent to use... doIndent (position.line(), newIndentInChars, align); }
unsigned int KDocumentTextBuffer::cursorToOffset_kte( const KTextEditor::Cursor &cursor ) { unsigned int offset = 0; for( int i = 0; i < cursor.line(); i++ ) { offset += countUnicodeCharacters(kDocument()->line(i)) + 1; // Add newline } offset += countUnicodeCharacters(kDocument()->line(cursor.line()).left(cursor.column())); return offset; }
void TextHistory::wrapLine(const KTextEditor::Cursor &position) { // create and add new entry Entry entry; entry.type = Entry::WrapLine; entry.line = position.line(); entry.column = position.column(); addEntry(entry); }
void DebugSession::jumpToCursor() { if (KDevelop::IDocument* doc = KDevelop::ICore::self()->documentController()->activeDocument()) { KTextEditor::Cursor cursor = doc->cursorPosition(); if ( cursor.isValid() ) { // TODO disable all other breakpoints addSimpleUserCommand(QString("jump " + QString::number(cursor.line() + 1)).toAscii()); } } }
Recorder::Recorder(KTextEditor::View *view, Manager *manager) : QObject(view), m_manager(manager), m_view(view) { connect(m_manager, SIGNAL(watchedKeySequencesChanged()), this, SLOT(reloadWatchedKeySequences())); connect(this, SIGNAL(detectedTypedKeySequence(const QString&)), m_manager, SLOT(keySequenceTyped(const QString&))); KTextEditor::Cursor cursor = m_view->cursorPosition(); m_oldLine = cursor.line(); m_oldCol = cursor.column(); reloadWatchedKeySequences(); }
void SwapFile::wrapLine (const KTextEditor::Cursor &position) { // skip if not open if (!m_swapfile.isOpen ()) return; // format: qint8, int, int m_stream << EA_WrapLine << position.line() << position.column(); m_needSync = true; }
void SwapFile::insertText (const KTextEditor::Cursor &position, const QString &text) { // skip if not open if (!m_swapfile.isOpen ()) return; // format: qint8, int, int, bytearray m_stream << EA_InsertText << position.line() << position.column() << text.toUtf8 (); m_needSync = true; }
void TextHistory::insertText(const KTextEditor::Cursor &position, int length, int oldLineLength) { // create and add new entry Entry entry; entry.type = Entry::InsertText; entry.line = position.line(); entry.column = position.column(); entry.length = length; entry.oldLineLength = oldLineLength; addEntry(entry); }
/** * Returns the current position of the cursor. * @param nLine Holds the line on which the cursor is currently located * @param nCol Holds the column on which the cursor is currently located * @return true if successful, false otherwise (cursor interface was not * obtained) */ bool EditorPage::getCursorPos(uint& nLine, uint& nCol) { int line, col; // Get the cursor position (adjusted to 1-based counting) const KTextEditor::Cursor c = m_pView->cursorPosition(); c.position(line, col); nLine = line; nCol = col; nLine++; nCol++; return true; }
bool KateNewCompletionModel::shouldStartCompletion(KTextEditor::View* view, const QString &insertedText, bool userInsertion, const KTextEditor::Cursor &position) { if (!userInsertion) return false; if(insertedText.isEmpty()) return false; KateView *v = qobject_cast<KateView*> (view); QString text = view->document()->line(position.line()).left(position.column()); static const QRegExp ktuan_new_class("((new \\w*)|(gen\\w*)|(get\\w*))$"); if (ktuan_new_class.indexIn(text) >= 0) return true; return false; }
void DebugSession::runToCursor() { if (KDevelop::IDocument* doc = KDevelop::ICore::self()->documentController()->activeDocument()) { KTextEditor::Cursor cursor = doc->cursorPosition(); if ( cursor.isValid() ) { // TODO disable all other breakpoints QString temporaryBreakpointLocation = doc->url().path() + ':' + QString::number(cursor.line() + 1); InternalPdbCommand* temporaryBreakpointCmd = new InternalPdbCommand(0, 0, "tbreak " + temporaryBreakpointLocation + '\n'); addCommand(temporaryBreakpointCmd); addSimpleInternalCommand("continue"); updateLocation(); } } }
/** * This returns the view line upon which realCursor is situated. * The view line is the number of lines in the view from the first line * The supplied cursor should be in real lines. */ int KateLayoutCache::viewLine(const KTextEditor::Cursor& realCursor) { if (realCursor.column() <= 0 || realCursor.line() < 0) return 0; KateLineLayoutPtr thisLine = line(realCursor.line()); for (int i = 0; i < thisLine->viewLineCount(); ++i) { const KateTextLayout& l = thisLine->viewLine(i); if (realCursor.column() >= l.startCol() && realCursor.column() < l.endCol()) return i; } return thisLine->viewLineCount() - 1; }
void TextCursor::setPosition(const KTextEditor::Cursor& position, bool init) { // any change or init? else do nothing if (!init && position.line() == line() && position.column() == m_column) return; // remove cursor from old block in any case if (m_block) m_block->removeCursor (this); // first: validate the line and column, else invalid if (position.column() < 0 || position.line () < 0 || position.line () >= m_buffer.lines ()) { if (!m_range) m_buffer.m_invalidCursors.insert (this); m_block = 0; m_line = m_column = -1; return; } // else, find block TextBlock *block = m_buffer.blockForIndex (m_buffer.blockForLine (position.line())); Q_ASSERT(block); // get line TextLine textLine = block->line (position.line()); #if 0 // this is no good idea, smart cursors don't do that, too, for non-wrapping cursors // now, validate column, else stay invalid if (position.column() > textLine->text().size()) { if (!m_range) m_buffer.m_invalidCursors.insert (this); m_block = 0; m_line = m_column = -1; return; } #endif // if cursor was invalid before, remove it from invalid cursor list if (!m_range && !m_block && !init) { Q_ASSERT(m_buffer.m_invalidCursors.contains (this)); m_buffer.m_invalidCursors.remove (this); } // else: valid cursor m_block = block; m_line = position.line () - m_block->startLine (); m_column = position.column (); m_block->insertCursor (this); }
/** * Initiate completion when there is \c #include on a line (\c m_range * in a result of \c parseIncludeDirective() not empty -- i.e. there is some file present) * and cursor placed within that range... despite of completeness of the whole line. */ bool IncludeHelperCompletionModel::shouldStartCompletion( KTextEditor::View* view , const QString& inserted_text , bool user_insertion , const KTextEditor::Cursor& position ) { kDebug(DEBUG_AREA) << "position=" << position << ", inserted_text=" << inserted_text << ", ui=" << user_insertion; m_should_complete = false; auto* doc = view->document(); // get current document auto line = doc->line(position.line()); // get current line auto* iface = qobject_cast<KTextEditor::HighlightInterface*>(doc); // Do nothing if no highlighting interface or not suitable document or // a place within it... (we won't to complete smth in non C++ files or comments for example) if (!iface || !isSuitableDocumentAndHighlighting(doc->mimeType(), iface->highlightingModeAt(position))) return m_should_complete; // Try to parse it... auto r = parseIncludeDirective(line, false); m_should_complete = r.m_range.isValid(); if (m_should_complete) { kDebug(DEBUG_AREA) << "range=" << r.m_range; m_should_complete = position.column() >= r.m_range.start().column() && position.column() <= r.m_range.end().column(); if (m_should_complete) { m_closer = r.close_char(); kDebug(DEBUG_AREA) << "closer=" << m_closer; } } else if (position.column() == line.length()) { auto text = tryToCompleteIncludeDirective(line.mid(0, position.column()).trimmed()); m_should_complete = !text.isEmpty(); if (m_should_complete) { /// \todo Hardcoded angle bracket! Better to check what file was selected /// (from system path or session specific) and replace it accordingly... text += QLatin1String(" <"); auto start = position; start.setColumn(0); auto range = KTextEditor::Range{start, position}; view->document()->replaceText(range, text); } } return m_should_complete; }
// TODO: will be a word in two lines ? QString EditorPage::getWordUnderCursor(uint* pPosInWord) { QString sLine; int nLine, nCol, nFrom, nTo, nLast, nLength; QChar ch; const KTextEditor::Cursor c = m_pView->cursorPosition(); // Get the line on which the cursor is positioned c.position(nLine, nCol); const KTextEditor::Cursor cFrom(nLine, 0); const KTextEditor::Cursor cTo = m_pDoc->endOfLine(nLine); KTextEditor::Range range(cFrom, cTo); sLine = m_pDoc->text(range); // Find the beginning of the current word for (nFrom = nCol; nFrom > 0;) { ch = sLine.at(nFrom - 1); if (!ch.isLetter() && !ch.isDigit() && ch != '_') break; nFrom--; } // Find the end of the current word nLast = sLine.length(); for (nTo = nCol; nTo < nLast;) { ch = sLine.at(nTo); if (!ch.isLetter() && !ch.isDigit() && ch != '_') break; nTo++; } // Mark empty words nLength = nTo - nFrom; if (nLength == 0) return QString::null; // Return the in-word position, if required if (pPosInWord != NULL) *pPosInWord = nCol - nFrom; // Extract the word under the cursor from the entire line return sLine.mid(nFrom, nLength); }
KateTextLayout KateLayoutCache::textLayout( const KTextEditor::Cursor & realCursor ) { /*if (realCursor >= viewCacheStart() && (realCursor < viewCacheEnd() || realCursor == viewCacheEnd() && !m_textLayouts.last().wrap())) foreach (const KateTextLayout& l, m_textLayouts) if (l.line() == realCursor.line() && (l.endCol() < realCursor.column() || !l.wrap())) return l;*/ return line(realCursor.line())->viewLine(viewLine(realCursor)); }
KTextEditor::Cursor KDocumentTextBuffer::offsetRelativeTo_kte(const KTextEditor::Cursor& cursor, unsigned int offset) { int lineno = cursor.line(); const QString& firstLine = kDocument()->line(lineno).mid(cursor.column()); unsigned int remaining = offset; int surrogates = surrogatesForCodePoints(firstLine, remaining); while ( remaining > 0 ) { remaining -= 1; // for the newline character lineno += 1; if ( remaining == 0 ) { surrogates = 0; break; } const QString& line = kDocument()->line(lineno); Q_ASSERT( lineno < kDocument()->lines() ); surrogates = surrogatesForCodePoints(line, remaining); } return KTextEditor::Cursor(lineno, lineno == cursor.line() ? cursor.column() + surrogates : surrogates); }
bool KateWordCompletionModel::shouldStartCompletion(KTextEditor::View* view, const QString &insertedText, bool userInsertion, const KTextEditor::Cursor &position) { if (!userInsertion) return false; if(insertedText.isEmpty()) return false; KateView *v = qobject_cast<KateView*> (view); QString text = view->document()->line(position.line()).left(position.column()); uint check=v->config()->wordCompletionMinimalWordLength(); if (check<=0) return true; int start=text.length(); int end=text.length()-check; if (end<0) return false; for (int i=start-1;i>=end;i--) { QChar c=text.at(i); if (! (c.isLetter() || (c.isNumber()) || c=='_') ) return false; } return true; }
// Return the range containing the word left of the cursor KTextEditor::Range KateWordCompletionModel::completionRange(KTextEditor::View* view, const KTextEditor::Cursor &position) { int line = position.line(); int col = position.column(); KTextEditor::Document *doc = view->document(); while ( col > 0 ) { QChar c = ( doc->character( KTextEditor::Cursor( line, col-1 ) ) ); if ( c.isLetterOrNumber() || c.isMark() || c == '_' ) { col--; continue; } break; } return KTextEditor::Range( KTextEditor::Cursor( line, col ), position ); }
// Return the range containing the word left of the cursor KTextEditor::Range KateNewCompletionModel::completionRange(KTextEditor::View* view, const KTextEditor::Cursor &position) { int line = position.line(); int col = position.column(); KTextEditor::Document *doc = view->document(); // ktuan java case: new List<Integer> // yieldXXX, Ent::load('XXX, genXXX, getXXX { QString text = view->document()->line(position.line()).left(position.column()); const static QRegExp ktuan_new_class("((new \\w*)|(gen\\w*)|(get\\w*))$"); int pos = ktuan_new_class.indexIn(text); if (pos >= 0) { return KTextEditor::Range( KTextEditor::Cursor( line, pos ), position ); } } return KTextEditor::Range( KTextEditor::Cursor( line, col ), position ); }
// Take the given QML line and check if it's a line of the form foo.bar: value. // Return ranges for the key and the value. const QPair<KTextEditor::Range, KTextEditor::Range> parseProperty(const QString& line, const KTextEditor::Cursor& position) { QStringList items = line.split(';'); QString matchingItem; int col_offset = -1; // This is to also support FooAnimation { foo: bar; baz: bang; duration: 200 } // or similar foreach ( const QString& item, items ) { col_offset += item.size() + 1; if ( position.column() < col_offset ) { matchingItem = item; break; } }
QString VariableController::expressionUnderCursor(KTextEditor::Document* doc, const KTextEditor::Cursor& cursor) { QString line = doc->line(cursor.line()); int index = cursor.column(); QChar c = line[index]; if (!c.isLetterOrNumber() && c != '_' && c != '$') return QString(); int start = Utils::expressionAt(line, index); int end = index; for (; end < line.size(); ++end) { QChar c = line[end]; if (!(c.isLetterOrNumber() || c == '_' || c == '$')) break; } if (!(start < end)) return QString(); QString expression(line.mid(start, end-start)); expression = expression.trimmed(); return expression; }
void ModelTest::completionItems() { KTextEditor::Document* doc = KTextEditor::Editor::instance()->createDocument(0); QFETCH(QString, text); QFETCH(QString, type); KTextEditor::Cursor position; QString textBeforeCursor = text.left(text.indexOf('|')); position.setLine(textBeforeCursor.count('\n')); position.setColumn(textBeforeCursor.mid(textBeforeCursor.lastIndexOf('\n')).length()); text.replace('|', ""); QTemporaryFile file("XXXXXXXXX."+type); file.open(); file.write(text.toUtf8()); file.close(); doc->openUrl(KUrl("file://"+QDir::current().absoluteFilePath(file.fileName()))); QCOMPARE(doc->mimeType(), QString("text/")+type); KTextEditor::View* view = doc->createView(0); CodeCompletionModel* model = new CodeCompletionModel(doc); QCOMPARE(model->rowCount(), 0); model->completionInvoked(view, model->completionRange(view, position), KTextEditor::CodeCompletionModel::ManualInvocation); QStringList completions; for (int i=0; i < model->rowCount(); ++i) { completions << model->data(model->index(i, CodeCompletionModel::Name), Qt::DisplayRole).toString(); } kDebug() << "completions" << completions; QFETCH(QStringList, result); foreach (const QString &i, result) { QVERIFY(completions.contains(i)); }
bool Recorder::eventFilter(QObject* /* o */, QEvent *e) { if (e->type() == QEvent::KeyPress) { QKeyEvent *keyEvent = (QKeyEvent*)(e); int curLine, curCol; KTextEditor::Cursor cursor = m_view->cursorPosition(); curLine = cursor.line(); curCol = cursor.column(); if(curLine != m_oldLine || m_oldCol+1 != curCol) { m_typedSequence.clear(); m_oldLine = curLine; m_oldCol = curCol; } else { ++m_oldCol; } m_typedSequence += keyEvent->text(); if(m_typedSequence.length() == m_maxSequenceLength + 1) { m_typedSequence = m_typedSequence.mid(1, m_typedSequence.length() - 1); } return seekForKeySequence(m_typedSequence); } return false; }
/** * We don't care about how many lines possible was inserted. Just consider * a current one. */ bool PreprocessorCompletionModel::shouldStartCompletion( KTextEditor::View* const view , const QString& /*inserted_text*/ , const bool /*user_insertion*/ , const KTextEditor::Cursor& position ) { m_should_complete = false; auto* const doc = view->document(); // get current document auto* const iface = qobject_cast<KTextEditor::HighlightInterface*>(doc); // Do nothing if no highlighting interface or not suitable document or // a place within it... (we won't to complete smth in non C++ files or comments for example) if (!iface || !isSuitableDocumentAndHighlighting(doc->mimeType(), iface->highlightingModeAt(position))) return false; auto text_before = doc->text({KTextEditor::Cursor(position.line(), 0), position}); kDebug(DEBUG_AREA) << "text_before=" << text_before; /// Check if current line starts w/ \c '#' which is a sign of a preprocessor directive. if (text_before[0] == '#') { text_before = text_before.remove(0, 1).trimmed(); kDebug(DEBUG_AREA) << "again text_before=" << text_before; /// Then make sure the text after it, is a subset of some /// hardcoded item from the \c COMPLETIONS table. m_should_complete = text_before.isEmpty() || std::any_of( begin(COMPLETIONS) , end(COMPLETIONS) , [&text_before](const auto& item) { auto text = item.text; const auto end_of_first_word = text.indexOf(' '); if (end_of_first_word != -1) // Strip tail of the completion item... only first word is interesting! text = text.left(end_of_first_word); return text_before.size() < text.size() && text.startsWith(text_before); } ); kDebug(DEBUG_AREA) << "m_should_complete=" << m_should_complete; return m_should_complete; } return false; }