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