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); }
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::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 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 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); }
// 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 ); }
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; }
/** * 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; }
/** * 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; }
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; }
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); }
// 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 ); }
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; }
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; }
bool KTEView::setCursorPosition( KTextEditor::Cursor position ) { kDebug() << "KTEView::setCursorPosition x: " << position.column() << " y: " << position.line() << "\n"; m_view->gotoLinePosition(position.line(), position.column()); return true; }
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(); } } }
KateLineLayoutPtr KateLayoutCache::line( const KTextEditor::Cursor & realCursor ) { return line(realCursor.line()); }
int KateLayoutCache::displayViewLine(const KTextEditor::Cursor& virtualCursor, bool limitToVisible) { KTextEditor::Cursor work = viewCacheStart(); // only try this with valid lines! if (work.isValid()) work.setLine(m_renderer->folding().lineToVisibleLine(work.line())); if (!work.isValid()) return virtualCursor.line(); int limit = m_textLayouts.count(); // Efficient non-word-wrapped path if (!m_renderer->view()->dynWordWrap()) { int ret = virtualCursor.line() - work.line(); if (limitToVisible && (ret < 0 || ret > limit)) return -1; else return ret; } if (work == virtualCursor) { return 0; } int ret = -(int)viewLine(viewCacheStart()); bool forwards = (work < virtualCursor); // FIXME switch to using ranges? faster? if (forwards) { while (work.line() != virtualCursor.line()) { ret += viewLineCount(m_renderer->folding().visibleLineToLine(work.line())); work.setLine(work.line() + 1); if (limitToVisible && ret > limit) return -1; } } else { while (work.line() != virtualCursor.line()) { work.setLine(work.line() - 1); ret -= viewLineCount(m_renderer->folding().visibleLineToLine(work.line())); if (limitToVisible && ret < 0) return -1; } } // final difference KTextEditor::Cursor realCursor = virtualCursor; realCursor.setLine(m_renderer->folding().visibleLineToLine(realCursor.line())); if (realCursor.column() == -1) realCursor.setColumn(m_renderer->doc()->lineLength(realCursor.line())); ret += viewLine(realCursor); if (limitToVisible && (ret < 0 || ret > limit)) return -1; return ret; }
bool KateLineLayout::includesCursor(const KTextEditor::Cursor& realCursor) const { return realCursor.line() == line(); }
void KateLayoutCache::updateViewCache(const KTextEditor::Cursor& startPos, int newViewLineCount, int viewLinesScrolled) { //kDebug( 13033 ) << startPos << " nvlc " << newViewLineCount << " vls " << viewLinesScrolled; int oldViewLineCount = m_textLayouts.count(); if (newViewLineCount == -1) newViewLineCount = oldViewLineCount; enableLayoutCache = true; int realLine; if (newViewLineCount == -1) realLine = m_renderer->folding().visibleLineToLine(m_renderer->folding().lineToVisibleLine(startPos.line())); else realLine = m_renderer->folding().visibleLineToLine(startPos.line()); int _viewLine = 0; if (wrap()) { // TODO check these assumptions are ok... probably they don't give much speedup anyway? if (startPos == m_startPos && m_textLayouts.count()) { _viewLine = m_textLayouts.first().viewLine(); } else if (viewLinesScrolled > 0 && viewLinesScrolled < m_textLayouts.count()) { _viewLine = m_textLayouts[viewLinesScrolled].viewLine(); } else { KateLineLayoutPtr l = line(realLine); if (l) { Q_ASSERT(l->isValid()); Q_ASSERT(l->length() >= startPos.column() || m_renderer->view()->wrapCursor()); for (; _viewLine < l->viewLineCount(); ++_viewLine) { const KateTextLayout& t = l->viewLine(_viewLine); if (t.startCol() >= startPos.column() || _viewLine == l->viewLineCount() - 1) goto foundViewLine; } // FIXME FIXME need to calculate past-end-of-line position here... Q_ASSERT(false); foundViewLine: Q_ASSERT(true); } } } m_startPos = startPos; // Move the text layouts if we've just scrolled... if (viewLinesScrolled != 0) { // loop backwards if we've just scrolled up... bool forwards = viewLinesScrolled >= 0 ? true : false; for (int z = forwards ? 0 : m_textLayouts.count() - 1; forwards ? (z < m_textLayouts.count()) : (z >= 0); forwards ? z++ : z--) { int oldZ = z + viewLinesScrolled; if (oldZ >= 0 && oldZ < m_textLayouts.count()) m_textLayouts[z] = m_textLayouts[oldZ]; } } // Resize functionality if (newViewLineCount > oldViewLineCount) { m_textLayouts.reserve(newViewLineCount); } else if (newViewLineCount < oldViewLineCount) { /* FIXME reintroduce... check we're not missing any int lastLine = m_textLayouts[newSize - 1].line(); for (int i = oldSize; i < newSize; i++) { const KateTextLayout& layout = m_textLayouts[i]; if (layout.line() > lastLine && !layout.viewLine()) layout.kateLineLayout()->layout()->setCacheEnabled(false); }*/ m_textLayouts.resize(newViewLineCount); } KateLineLayoutPtr l = line(realLine); for (int i = 0; i < newViewLineCount; ++i) { if (!l) { if (i < m_textLayouts.count()) { if (m_textLayouts[i].isValid()) m_textLayouts[i] = KateTextLayout::invalid(); } else { m_textLayouts.append(KateTextLayout::invalid()); } continue; } Q_ASSERT(l->isValid()); Q_ASSERT(_viewLine < l->viewLineCount()); if (i < m_textLayouts.count()) { bool dirty = false; if (m_textLayouts[i].line() != realLine || m_textLayouts[i].viewLine() != _viewLine || (!m_textLayouts[i].isValid() && l->viewLine(_viewLine).isValid())) dirty = true; m_textLayouts[i] = l->viewLine(_viewLine); if (dirty) m_textLayouts[i].setDirty(true); } else { m_textLayouts.append(l->viewLine(_viewLine)); } //kDebug( 13033 ) << "Laid out line " << realLine << " (" << l << "), viewLine " << _viewLine << " (" << m_textLayouts[i].kateLineLayout().data() << ")"; //m_textLayouts[i].debugOutput(); _viewLine++; if (_viewLine > l->viewLineCount() - 1) { int virtualLine = l->virtualLine() + 1; realLine = m_renderer->folding().visibleLineToLine(virtualLine); _viewLine = 0; if (realLine < m_renderer->doc()->lines()) { l = line(realLine, virtualLine); } else { l = 0; } } } enableLayoutCache = false; }
/** Conversion function from KTextEditor::Cursor to QtScript cursor */ static QScriptValue cursorToScriptValue(QScriptEngine *engine, const KTextEditor::Cursor &cursor) { QString code = QString("new Cursor(%1, %2);").arg(cursor.line()) .arg(cursor.column()); return engine->evaluate(code); }
int KileScriptDocument::nextNonSpaceColumn(const KTextEditor::Cursor& cursor) { return nextNonSpaceColumn(cursor.line(), cursor.column()); }
bool KileScriptDocument::matchesAt(const KTextEditor::Cursor& cursor, const QString &s) { QString textline = m_document->line(cursor.line()); return textline.mid(cursor.column()).startsWith(s); }
bool KileScriptDocument::truncate(const KTextEditor::Cursor& cursor) { return truncate(cursor.line(), cursor.column()); }
QPoint KTEView::cursorToCoordinate( const KTextEditor::Cursor& cursor ) const { return QPoint( cursor.column(), cursor.line() ); }