File indexing completed on 2024-04-28 03:57:42

0001 /*
0002     SPDX-FileCopyrightText: 2008 Paul Giannaros <paul@giannaros.org>
0003     SPDX-FileCopyrightText: 2009-2018 Dominik Haumann <dhaumann@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "katescriptdocument.h"
0009 
0010 #include "katebuffer.h"
0011 #include "kateconfig.h"
0012 #include "katedocument.h"
0013 #include "katehighlight.h"
0014 #include "katepartdebug.h"
0015 #include "katescript.h"
0016 #include "scriptcursor.h"
0017 #include "scriptrange.h"
0018 
0019 #include <QJSEngine>
0020 #include <ktexteditor/documentcursor.h>
0021 
0022 KateScriptDocument::KateScriptDocument(QJSEngine *engine, QObject *parent)
0023     : QObject(parent)
0024     , m_document(nullptr)
0025     , m_engine(engine)
0026 {
0027 }
0028 
0029 void KateScriptDocument::setDocument(KTextEditor::DocumentPrivate *document)
0030 {
0031     m_document = document;
0032 }
0033 
0034 KTextEditor::DocumentPrivate *KateScriptDocument::document()
0035 {
0036     return m_document;
0037 }
0038 
0039 int KateScriptDocument::defStyleNum(int line, int column)
0040 {
0041     return m_document->defStyleNum(line, column);
0042 }
0043 
0044 int KateScriptDocument::defStyleNum(const QJSValue &jscursor)
0045 {
0046     const auto cursor = cursorFromScriptValue(jscursor);
0047     return defStyleNum(cursor.line(), cursor.column());
0048 }
0049 
0050 bool KateScriptDocument::isCode(int line, int column)
0051 {
0052     const int defaultStyle = defStyleNum(line, column);
0053     return _isCode(defaultStyle);
0054 }
0055 
0056 bool KateScriptDocument::isCode(const QJSValue &jscursor)
0057 {
0058     const auto cursor = cursorFromScriptValue(jscursor);
0059     return isCode(cursor.line(), cursor.column());
0060 }
0061 
0062 bool KateScriptDocument::isComment(int line, int column)
0063 {
0064     return m_document->isComment(line, column);
0065 }
0066 
0067 bool KateScriptDocument::isComment(const QJSValue &jscursor)
0068 {
0069     const auto cursor = cursorFromScriptValue(jscursor);
0070     return isComment(cursor.line(), cursor.column());
0071 }
0072 
0073 bool KateScriptDocument::isString(int line, int column)
0074 {
0075     const int defaultStyle = defStyleNum(line, column);
0076     return defaultStyle == KSyntaxHighlighting::Theme::TextStyle::String;
0077 }
0078 
0079 bool KateScriptDocument::isString(const QJSValue &jscursor)
0080 {
0081     const auto cursor = cursorFromScriptValue(jscursor);
0082     return isString(cursor.line(), cursor.column());
0083 }
0084 
0085 bool KateScriptDocument::isRegionMarker(int line, int column)
0086 {
0087     const int defaultStyle = defStyleNum(line, column);
0088     return defaultStyle == KSyntaxHighlighting::Theme::TextStyle::RegionMarker;
0089 }
0090 
0091 bool KateScriptDocument::isRegionMarker(const QJSValue &jscursor)
0092 {
0093     const auto cursor = cursorFromScriptValue(jscursor);
0094     return isRegionMarker(cursor.line(), cursor.column());
0095 }
0096 
0097 bool KateScriptDocument::isChar(int line, int column)
0098 {
0099     const int defaultStyle = defStyleNum(line, column);
0100     return defaultStyle == KSyntaxHighlighting::Theme::TextStyle::Char;
0101 }
0102 
0103 bool KateScriptDocument::isChar(const QJSValue &jscursor)
0104 {
0105     const auto cursor = cursorFromScriptValue(jscursor);
0106     return isChar(cursor.line(), cursor.column());
0107 }
0108 
0109 bool KateScriptDocument::isOthers(int line, int column)
0110 {
0111     const int defaultStyle = defStyleNum(line, column);
0112     return defaultStyle == KSyntaxHighlighting::Theme::TextStyle::Others;
0113 }
0114 
0115 bool KateScriptDocument::isOthers(const QJSValue &jscursor)
0116 {
0117     const auto cursor = cursorFromScriptValue(jscursor);
0118     return isOthers(cursor.line(), cursor.column());
0119 }
0120 
0121 int KateScriptDocument::firstVirtualColumn(int line)
0122 {
0123     const int tabWidth = m_document->config()->tabWidth();
0124     const auto textLine = m_document->plainKateTextLine(line);
0125     if (textLine.firstChar() == -1) {
0126         return -1;
0127     }
0128     return textLine.indentDepth(tabWidth);
0129 }
0130 
0131 int KateScriptDocument::lastVirtualColumn(int line)
0132 {
0133     const int tabWidth = m_document->config()->tabWidth();
0134     const auto textLine = m_document->plainKateTextLine(line);
0135     const auto lastPos = textLine.lastChar();
0136     if (lastPos == -1) {
0137         return -1;
0138     }
0139     return textLine.toVirtualColumn(lastPos, tabWidth);
0140 }
0141 
0142 int KateScriptDocument::toVirtualColumn(int line, int column)
0143 {
0144     const int tabWidth = m_document->config()->tabWidth();
0145     const auto textLine = m_document->plainKateTextLine(line);
0146     if (column < 0 || column > textLine.length()) {
0147         return -1;
0148     }
0149     return textLine.toVirtualColumn(column, tabWidth);
0150 }
0151 
0152 int KateScriptDocument::toVirtualColumn(const QJSValue &jscursor)
0153 {
0154     const auto cursor = cursorFromScriptValue(jscursor);
0155     return toVirtualColumn(cursor.line(), cursor.column());
0156 }
0157 
0158 QJSValue KateScriptDocument::toVirtualCursor(int line, int column)
0159 {
0160     const KTextEditor::Cursor cursor(line, toVirtualColumn(line, column));
0161     return cursorToScriptValue(m_engine, cursor);
0162 }
0163 
0164 QJSValue KateScriptDocument::toVirtualCursor(const QJSValue &jscursor)
0165 {
0166     const auto cursor = cursorFromScriptValue(jscursor);
0167     return toVirtualCursor(cursor.line(), cursor.column());
0168 }
0169 
0170 int KateScriptDocument::fromVirtualColumn(int line, int virtualColumn)
0171 {
0172     const int tabWidth = m_document->config()->tabWidth();
0173     const auto textLine = m_document->plainKateTextLine(line);
0174     if (virtualColumn < 0 || virtualColumn > textLine.virtualLength(tabWidth)) {
0175         return -1;
0176     }
0177     return textLine.fromVirtualColumn(virtualColumn, tabWidth);
0178 }
0179 
0180 int KateScriptDocument::fromVirtualColumn(const QJSValue &jscursor)
0181 {
0182     const auto cursor = cursorFromScriptValue(jscursor);
0183     return fromVirtualColumn(cursor.line(), cursor.column());
0184 }
0185 
0186 QJSValue KateScriptDocument::fromVirtualCursor(int line, int column)
0187 {
0188     const KTextEditor::Cursor cursor(line, fromVirtualColumn(line, column));
0189     return cursorToScriptValue(m_engine, cursor);
0190 }
0191 
0192 QJSValue KateScriptDocument::fromVirtualCursor(const QJSValue &jscursor)
0193 {
0194     const auto cursor = cursorFromScriptValue(jscursor);
0195     return fromVirtualCursor(cursor.line(), cursor.column());
0196 }
0197 
0198 KTextEditor::Cursor KateScriptDocument::rfindInternal(int line, int column, const QString &text, int attribute)
0199 {
0200     KTextEditor::DocumentCursor cursor(document(), line, column);
0201     const int start = cursor.line();
0202 
0203     do {
0204         const auto textLine = m_document->plainKateTextLine(cursor.line());
0205 
0206         if (cursor.line() != start) {
0207             cursor.setColumn(textLine.length());
0208         } else if (column >= textLine.length()) {
0209             cursor.setColumn(qMax(textLine.length(), 0));
0210         }
0211 
0212         int foundAt;
0213         while ((foundAt = QStringView(textLine.text()).left(cursor.column()).lastIndexOf(text)) >= 0) {
0214             bool hasStyle = true;
0215             if (attribute != -1) {
0216                 const KSyntaxHighlighting::Theme::TextStyle ds = m_document->highlight()->defaultStyleForAttribute(textLine.attribute(foundAt));
0217                 hasStyle = (ds == attribute);
0218             }
0219 
0220             if (hasStyle) {
0221                 return KTextEditor::Cursor(cursor.line(), foundAt);
0222             } else {
0223                 cursor.setColumn(foundAt);
0224             }
0225         }
0226     } while (cursor.gotoPreviousLine());
0227 
0228     return KTextEditor::Cursor::invalid();
0229 }
0230 
0231 KTextEditor::Cursor KateScriptDocument::rfind(KTextEditor::Cursor cursor, const QString &text, int attribute)
0232 {
0233     return rfindInternal(cursor.line(), cursor.column(), text, attribute);
0234 }
0235 
0236 QJSValue KateScriptDocument::rfind(int line, int column, const QString &text, int attribute)
0237 {
0238     return cursorToScriptValue(m_engine, rfindInternal(line, column, text, attribute));
0239 }
0240 
0241 QJSValue KateScriptDocument::rfind(const QJSValue &jscursor, const QString &text, int attribute)
0242 {
0243     KTextEditor::Cursor cursor = cursorFromScriptValue(jscursor);
0244     return cursorToScriptValue(m_engine, rfind(cursor, text, attribute));
0245 }
0246 
0247 KTextEditor::Cursor KateScriptDocument::anchorInternal(int line, int column, QChar character)
0248 {
0249     QChar lc;
0250     QChar rc;
0251     if (character == QLatin1Char('(') || character == QLatin1Char(')')) {
0252         lc = QLatin1Char('(');
0253         rc = QLatin1Char(')');
0254     } else if (character == QLatin1Char('{') || character == QLatin1Char('}')) {
0255         lc = QLatin1Char('{');
0256         rc = QLatin1Char('}');
0257     } else if (character == QLatin1Char('[') || character == QLatin1Char(']')) {
0258         lc = QLatin1Char('[');
0259         rc = QLatin1Char(']');
0260     } else {
0261         qCDebug(LOG_KTE) << "invalid anchor character:" << character << " allowed are: (){}[]";
0262         return KTextEditor::Cursor::invalid();
0263     }
0264 
0265     auto *highlighter = m_document->highlight();
0266     auto isCodePos = [highlighter](const Kate::TextLine &currentLine, int i) {
0267         const KSyntaxHighlighting::Theme::TextStyle ds = highlighter->defaultStyleForAttribute(currentLine.attribute(i));
0268         return _isCode(ds);
0269     };
0270 
0271     // Move backwards char by char and find the opening character
0272     int count = 1;
0273     for (int l = line; l >= 0; --l) {
0274         const Kate::TextLine currentLine = document()->buffer().plainLine(l);
0275         const QString &lineText = currentLine.text();
0276         if (l < line) {
0277             // If the line is first line, we use the column
0278             // specified by the caller of this function
0279             // otherwise we start at line length
0280             column = lineText.length();
0281         }
0282         for (int i = column - 1; i >= 0; --i) {
0283             const QChar ch = lineText[i];
0284             if (ch == lc && isCodePos(currentLine, i)) {
0285                 --count;
0286             } else if (ch == rc && isCodePos(currentLine, i)) {
0287                 ++count;
0288             }
0289 
0290             if (count == 0) {
0291                 return KTextEditor::Cursor(l, i);
0292             }
0293         }
0294     }
0295 
0296     return KTextEditor::Cursor::invalid();
0297 }
0298 
0299 KTextEditor::Cursor KateScriptDocument::anchor(KTextEditor::Cursor cursor, QChar character)
0300 {
0301     return anchorInternal(cursor.line(), cursor.column(), character);
0302 }
0303 
0304 QJSValue KateScriptDocument::anchor(int line, int column, QChar character)
0305 {
0306     return cursorToScriptValue(m_engine, anchorInternal(line, column, character));
0307 }
0308 
0309 QJSValue KateScriptDocument::anchor(const QJSValue &jscursor, QChar character)
0310 {
0311     KTextEditor::Cursor cursor = cursorFromScriptValue(jscursor);
0312     return anchor(cursor.line(), cursor.column(), character);
0313 }
0314 
0315 bool KateScriptDocument::startsWith(int line, const QString &pattern, bool skipWhiteSpaces)
0316 {
0317     Kate::TextLine textLine = m_document->plainKateTextLine(line);
0318 
0319     if (skipWhiteSpaces) {
0320         return textLine.matchesAt(textLine.firstChar(), pattern);
0321     }
0322 
0323     return textLine.startsWith(pattern);
0324 }
0325 
0326 bool KateScriptDocument::endsWith(int line, const QString &pattern, bool skipWhiteSpaces)
0327 {
0328     Kate::TextLine textLine = m_document->plainKateTextLine(line);
0329 
0330     if (skipWhiteSpaces) {
0331         return textLine.matchesAt(textLine.lastChar() - pattern.length() + 1, pattern);
0332     }
0333 
0334     return textLine.endsWith(pattern);
0335 }
0336 
0337 QString KateScriptDocument::fileName()
0338 {
0339     return m_document->documentName();
0340 }
0341 
0342 QString KateScriptDocument::url()
0343 {
0344     return m_document->url().toString();
0345 }
0346 
0347 QString KateScriptDocument::mimeType()
0348 {
0349     return m_document->mimeType();
0350 }
0351 
0352 QString KateScriptDocument::encoding()
0353 {
0354     return m_document->encoding();
0355 }
0356 
0357 QString KateScriptDocument::highlightingMode()
0358 {
0359     return m_document->highlightingMode();
0360 }
0361 
0362 QStringList KateScriptDocument::embeddedHighlightingModes()
0363 {
0364     return m_document->embeddedHighlightingModes();
0365 }
0366 
0367 QString KateScriptDocument::highlightingModeAt(const QJSValue &jspos)
0368 {
0369     return m_document->highlightingModeAt(cursorFromScriptValue(jspos));
0370 }
0371 
0372 bool KateScriptDocument::isModified()
0373 {
0374     return m_document->isModified();
0375 }
0376 
0377 QString KateScriptDocument::text()
0378 {
0379     return m_document->text();
0380 }
0381 
0382 QString KateScriptDocument::text(int fromLine, int fromColumn, int toLine, int toColumn)
0383 {
0384     const KTextEditor::Range range(fromLine, fromColumn, toLine, toColumn);
0385     return m_document->text(range);
0386 }
0387 
0388 QString KateScriptDocument::text(const QJSValue &jsfrom, const QJSValue &jsto)
0389 {
0390     const KTextEditor::Cursor from = cursorFromScriptValue(jsfrom);
0391     const KTextEditor::Cursor to = cursorFromScriptValue(jsto);
0392     return text(from.line(), from.column(), to.line(), to.column());
0393 }
0394 
0395 QString KateScriptDocument::text(const QJSValue &jsrange)
0396 {
0397     const auto range = rangeFromScriptValue(jsrange);
0398     return text(range.start().line(), range.start().column(), range.end().line(), range.end().column());
0399 }
0400 
0401 QString KateScriptDocument::line(int line)
0402 {
0403     return m_document->line(line);
0404 }
0405 
0406 QString KateScriptDocument::wordAt(int line, int column)
0407 {
0408     const KTextEditor::Cursor cursor(line, column);
0409     return m_document->wordAt(cursor);
0410 }
0411 
0412 QString KateScriptDocument::wordAt(const QJSValue &jscursor)
0413 {
0414     const auto cursor = cursorFromScriptValue(jscursor);
0415     return wordAt(cursor.line(), cursor.column());
0416 }
0417 
0418 QJSValue KateScriptDocument::wordRangeAt(int line, int column)
0419 {
0420     const KTextEditor::Cursor cursor(line, column);
0421     return rangeToScriptValue(m_engine, m_document->wordRangeAt(cursor));
0422 }
0423 
0424 QJSValue KateScriptDocument::wordRangeAt(const QJSValue &jscursor)
0425 {
0426     const auto cursor = cursorFromScriptValue(jscursor);
0427     return wordRangeAt(cursor.line(), cursor.column());
0428 }
0429 
0430 QString KateScriptDocument::charAt(int line, int column)
0431 {
0432     const KTextEditor::Cursor cursor(line, column);
0433     const QChar c = m_document->characterAt(cursor);
0434     return c.isNull() ? QString() : QString(c);
0435 }
0436 
0437 QString KateScriptDocument::charAt(const QJSValue &jscursor)
0438 {
0439     const auto cursor = cursorFromScriptValue(jscursor);
0440     return charAt(cursor.line(), cursor.column());
0441 }
0442 
0443 QString KateScriptDocument::firstChar(int line)
0444 {
0445     Kate::TextLine textLine = m_document->plainKateTextLine(line);
0446     // check for isNull(), as the returned character then would be "\0"
0447     const QChar c = textLine.at(textLine.firstChar());
0448     return c.isNull() ? QString() : QString(c);
0449 }
0450 
0451 QString KateScriptDocument::lastChar(int line)
0452 {
0453     Kate::TextLine textLine = m_document->plainKateTextLine(line);
0454     // check for isNull(), as the returned character then would be "\0"
0455     const QChar c = textLine.at(textLine.lastChar());
0456     return c.isNull() ? QString() : QString(c);
0457 }
0458 
0459 bool KateScriptDocument::isSpace(int line, int column)
0460 {
0461     const KTextEditor::Cursor cursor(line, column);
0462     return m_document->characterAt(cursor).isSpace();
0463 }
0464 
0465 bool KateScriptDocument::isSpace(const QJSValue &jscursor)
0466 {
0467     const auto cursor = cursorFromScriptValue(jscursor);
0468     return isSpace(cursor.line(), cursor.column());
0469 }
0470 
0471 bool KateScriptDocument::matchesAt(int line, int column, const QString &s)
0472 {
0473     Kate::TextLine textLine = m_document->plainKateTextLine(line);
0474     return textLine.matchesAt(column, s);
0475 }
0476 
0477 bool KateScriptDocument::matchesAt(const QJSValue &jscursor, const QString &s)
0478 {
0479     const auto cursor = cursorFromScriptValue(jscursor);
0480     return matchesAt(cursor.line(), cursor.column(), s);
0481 }
0482 
0483 bool KateScriptDocument::setText(const QString &s)
0484 {
0485     return m_document->setText(s);
0486 }
0487 
0488 bool KateScriptDocument::clear()
0489 {
0490     return m_document->clear();
0491 }
0492 
0493 bool KateScriptDocument::truncate(int line, int column)
0494 {
0495     Kate::TextLine textLine = m_document->plainKateTextLine(line);
0496     if (textLine.text().size() < column) {
0497         return false;
0498     }
0499     return removeText(line, column, line, textLine.text().size() - column);
0500 }
0501 
0502 bool KateScriptDocument::truncate(const QJSValue &jscursor)
0503 {
0504     const auto cursor = cursorFromScriptValue(jscursor);
0505     return truncate(cursor.line(), cursor.column());
0506 }
0507 
0508 bool KateScriptDocument::insertText(int line, int column, const QString &s)
0509 {
0510     KTextEditor::Cursor cursor(line, column);
0511     return m_document->insertText(cursor, s);
0512 }
0513 
0514 bool KateScriptDocument::insertText(const QJSValue &jscursor, const QString &s)
0515 {
0516     const auto cursor = cursorFromScriptValue(jscursor);
0517     return insertText(cursor.line(), cursor.column(), s);
0518 }
0519 
0520 bool KateScriptDocument::removeText(int fromLine, int fromColumn, int toLine, int toColumn)
0521 {
0522     const KTextEditor::Range range(fromLine, fromColumn, toLine, toColumn);
0523     return m_document->removeText(range);
0524 }
0525 
0526 bool KateScriptDocument::removeText(const QJSValue &jsfrom, const QJSValue &jsto)
0527 {
0528     const KTextEditor::Cursor from = cursorFromScriptValue(jsfrom);
0529     const KTextEditor::Cursor to = cursorFromScriptValue(jsto);
0530     return removeText(from.line(), from.column(), to.line(), to.column());
0531 }
0532 
0533 bool KateScriptDocument::removeText(const QJSValue &jsrange)
0534 {
0535     const auto range = rangeFromScriptValue(jsrange);
0536     return removeText(range.start().line(), range.start().column(), range.end().line(), range.end().column());
0537 }
0538 
0539 bool KateScriptDocument::insertLine(int line, const QString &s)
0540 {
0541     return m_document->insertLine(line, s);
0542 }
0543 
0544 bool KateScriptDocument::removeLine(int line)
0545 {
0546     return m_document->removeLine(line);
0547 }
0548 
0549 bool KateScriptDocument::wrapLine(int line, int column)
0550 {
0551     return m_document->editWrapLine(line, column);
0552 }
0553 
0554 bool KateScriptDocument::wrapLine(const QJSValue &jscursor)
0555 {
0556     const auto cursor = cursorFromScriptValue(jscursor);
0557     return wrapLine(cursor.line(), cursor.column());
0558 }
0559 
0560 void KateScriptDocument::joinLines(int startLine, int endLine)
0561 {
0562     m_document->joinLines(startLine, endLine);
0563 }
0564 
0565 int KateScriptDocument::lines()
0566 {
0567     return m_document->lines();
0568 }
0569 
0570 bool KateScriptDocument::isLineModified(int line)
0571 {
0572     return m_document->isLineModified(line);
0573 }
0574 
0575 bool KateScriptDocument::isLineSaved(int line)
0576 {
0577     return m_document->isLineSaved(line);
0578 }
0579 
0580 bool KateScriptDocument::isLineTouched(int line)
0581 {
0582     return m_document->isLineTouched(line);
0583 }
0584 
0585 int KateScriptDocument::findTouchedLine(int startLine, bool down)
0586 {
0587     return m_document->findTouchedLine(startLine, down);
0588 }
0589 
0590 int KateScriptDocument::length()
0591 {
0592     return m_document->totalCharacters();
0593 }
0594 
0595 int KateScriptDocument::lineLength(int line)
0596 {
0597     return m_document->lineLength(line);
0598 }
0599 
0600 void KateScriptDocument::editBegin()
0601 {
0602     m_document->editStart();
0603 }
0604 
0605 void KateScriptDocument::editEnd()
0606 {
0607     m_document->editEnd();
0608 }
0609 
0610 bool KateScriptDocument::isValidTextPosition(int line, int column)
0611 {
0612     return m_document->isValidTextPosition(KTextEditor::Cursor(line, column));
0613 }
0614 
0615 bool KateScriptDocument::isValidTextPosition(const QJSValue &cursor)
0616 {
0617     return m_document->isValidTextPosition(cursorFromScriptValue(cursor));
0618 }
0619 
0620 int KateScriptDocument::firstColumn(int line)
0621 {
0622     Kate::TextLine textLine = m_document->plainKateTextLine(line);
0623     return textLine.firstChar();
0624 }
0625 
0626 int KateScriptDocument::lastColumn(int line)
0627 {
0628     Kate::TextLine textLine = m_document->plainKateTextLine(line);
0629     return textLine.lastChar();
0630 }
0631 
0632 int KateScriptDocument::prevNonSpaceColumn(int line, int column)
0633 {
0634     Kate::TextLine textLine = m_document->plainKateTextLine(line);
0635     return textLine.previousNonSpaceChar(column);
0636 }
0637 
0638 int KateScriptDocument::prevNonSpaceColumn(const QJSValue &jscursor)
0639 {
0640     const auto cursor = cursorFromScriptValue(jscursor);
0641     return prevNonSpaceColumn(cursor.line(), cursor.column());
0642 }
0643 
0644 int KateScriptDocument::nextNonSpaceColumn(int line, int column)
0645 {
0646     Kate::TextLine textLine = m_document->plainKateTextLine(line);
0647     return textLine.nextNonSpaceChar(column);
0648 }
0649 
0650 int KateScriptDocument::nextNonSpaceColumn(const QJSValue &jscursor)
0651 {
0652     const auto cursor = cursorFromScriptValue(jscursor);
0653     return nextNonSpaceColumn(cursor.line(), cursor.column());
0654 }
0655 
0656 int KateScriptDocument::prevNonEmptyLine(int line)
0657 {
0658     const int startLine = line;
0659     for (int currentLine = startLine; currentLine >= 0; --currentLine) {
0660         Kate::TextLine textLine = m_document->plainKateTextLine(currentLine);
0661         if (textLine.firstChar() != -1) {
0662             return currentLine;
0663         }
0664     }
0665     return -1;
0666 }
0667 
0668 int KateScriptDocument::nextNonEmptyLine(int line)
0669 {
0670     const int startLine = line;
0671     for (int currentLine = startLine; currentLine < m_document->lines(); ++currentLine) {
0672         Kate::TextLine textLine = m_document->plainKateTextLine(currentLine);
0673         if (textLine.firstChar() != -1) {
0674             return currentLine;
0675         }
0676     }
0677     return -1;
0678 }
0679 
0680 bool KateScriptDocument::isInWord(const QString &character, int attribute)
0681 {
0682     return m_document->highlight()->isInWord(character.at(0), attribute);
0683 }
0684 
0685 bool KateScriptDocument::canBreakAt(const QString &character, int attribute)
0686 {
0687     return m_document->highlight()->canBreakAt(character.at(0), attribute);
0688 }
0689 
0690 bool KateScriptDocument::canComment(int startAttribute, int endAttribute)
0691 {
0692     return m_document->highlight()->canComment(startAttribute, endAttribute);
0693 }
0694 
0695 QString KateScriptDocument::commentMarker(int attribute)
0696 {
0697     return m_document->highlight()->getCommentSingleLineStart(attribute);
0698 }
0699 
0700 QString KateScriptDocument::commentStart(int attribute)
0701 {
0702     return m_document->highlight()->getCommentStart(attribute);
0703 }
0704 
0705 QString KateScriptDocument::commentEnd(int attribute)
0706 {
0707     return m_document->highlight()->getCommentEnd(attribute);
0708 }
0709 
0710 QJSValue KateScriptDocument::documentRange()
0711 {
0712     return rangeToScriptValue(m_engine, m_document->documentRange());
0713 }
0714 
0715 QJSValue KateScriptDocument::documentEnd()
0716 {
0717     return cursorToScriptValue(m_engine, m_document->documentEnd());
0718 }
0719 
0720 int KateScriptDocument::attribute(int line, int column)
0721 {
0722     Kate::TextLine textLine = m_document->kateTextLine(line);
0723     return textLine.attribute(column);
0724 }
0725 
0726 int KateScriptDocument::attribute(const QJSValue &jscursor)
0727 {
0728     const auto cursor = cursorFromScriptValue(jscursor);
0729     return attribute(cursor.line(), cursor.column());
0730 }
0731 
0732 bool KateScriptDocument::isAttribute(int line, int column, int attr)
0733 {
0734     return attr == attribute(line, column);
0735 }
0736 
0737 bool KateScriptDocument::isAttribute(const QJSValue &jscursor, int attr)
0738 {
0739     const auto cursor = cursorFromScriptValue(jscursor);
0740     return isAttribute(cursor.line(), cursor.column(), attr);
0741 }
0742 
0743 QString KateScriptDocument::attributeName(int line, int column)
0744 {
0745     return m_document->highlight()->nameForAttrib(document()->plainKateTextLine(line).attribute(column));
0746 }
0747 
0748 QString KateScriptDocument::attributeName(const QJSValue &jscursor)
0749 {
0750     const auto cursor = cursorFromScriptValue(jscursor);
0751     return attributeName(cursor.line(), cursor.column());
0752 }
0753 
0754 bool KateScriptDocument::isAttributeName(int line, int column, const QString &name)
0755 {
0756     return name == attributeName(line, column);
0757 }
0758 
0759 bool KateScriptDocument::isAttributeName(const QJSValue &jscursor, const QString &name)
0760 {
0761     const auto cursor = cursorFromScriptValue(jscursor);
0762     return isAttributeName(cursor.line(), cursor.column(), name);
0763 }
0764 
0765 QString KateScriptDocument::variable(const QString &s)
0766 {
0767     return m_document->variable(s);
0768 }
0769 
0770 void KateScriptDocument::setVariable(const QString &s, const QString &v)
0771 {
0772     m_document->setVariable(s, v);
0773 }
0774 
0775 bool KateScriptDocument::_isCode(int defaultStyle)
0776 {
0777     using S = KSyntaxHighlighting::Theme::TextStyle;
0778     return (defaultStyle != S::Comment && defaultStyle != S::Alert && defaultStyle != S::String && defaultStyle != S::RegionMarker && defaultStyle != S::Char
0779             && defaultStyle != S::Others);
0780 }
0781 
0782 void KateScriptDocument::indent(const QJSValue &jsrange, int change)
0783 {
0784     const auto range = rangeFromScriptValue(jsrange);
0785     m_document->indent(range, change);
0786 }
0787 
0788 #include "moc_katescriptdocument.cpp"