// Scan throughout the entire document for possible completions, // ignoring any dublets const QStringList KateWordCompletionModel::allMatches( KTextEditor::View *view, const KTextEditor::Range &range ) const { KTextEditor::Document *doc = view->document(); QString match_str = doc->text(range); QString s, m; QSet<QString> seen; QStringList l; int i( 0 ); int pos( 0 ); QRegExp re( "\\b(" + match_str + "\\w{1,})" ); while( i < doc->lines() ) { s = doc->line( i ); pos = 0; while ( pos >= 0 ) { pos = re.indexIn( s, pos ); if ( pos >= 0 ) { // typing in the middle of a word if ( ! ( i == range.start().line() && pos == range.start().column() ) ) { m = re.cap( 1 ); if ( ! seen.contains( m ) ) { seen.insert( m ); l << m; } } pos += re.matchedLength(); } } i++; } // Global completion // int db_area = KDebug::registerArea("ktuan-debug"); QMap<QString, QStringList>::const_iterator ci = doc_word_list.constBegin(); while (ci != doc_word_list.constEnd()) { if (ci.key() != doc->url().prettyUrl()) { QStringList list = ci.value(); foreach (QString word, list) { // kDebug(db_area) << "complete word " << word; if (word.startsWith(match_str) && !seen.contains(word)) { // kDebug(db_area) << "Global completion"; seen.insert(word); l << word; } } } ++ci; }
// ### the code below is slightly modified from kdelibs/kate/part/katedialogs, // class KateModOnHdPrompt. void KateMwModOnHdDialog::slotDiff() { if ( !btnDiff->isEnabled()) // diff button already pressed, proc not finished yet return; if ( ! twDocuments->currentItem() ) return; KTextEditor::Document *doc = ((KateDocItem*)twDocuments->currentItem())->document; // don't try to diff a deleted file if ( KateDocManager::self()->documentInfo( doc )->modifiedOnDiscReason == KTextEditor::ModificationInterface::OnDiskDeleted ) return; if (m_diffFile) return; m_diffFile = new KTemporaryFile(); m_diffFile->open(); // Start a KProcess that creates a diff m_proc = new KProcess( this ); m_proc->setOutputChannelMode( KProcess::MergedChannels ); *m_proc << "diff" << "-ub" << "-" << doc->url().toLocalFile(); connect( m_proc, SIGNAL(readyRead()), this, SLOT(slotDataAvailable()) ); connect( m_proc, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(slotPDone()) ); setCursor( Qt::WaitCursor ); btnDiff->setEnabled(false); m_proc->start(); QTextStream ts(m_proc); int lastln = doc->lines(); for ( int l = 0; l < lastln; ++l ) ts << doc->line( l ) << '\n'; ts.flush(); m_proc->closeWriteChannel(); }
// Scan throughout the entire document for possible completions, // ignoring any dublets const QStringList KateWordCompletionModel::allMatches( KTextEditor::View *view, const KTextEditor::Range &range ) const { QStringList l; int i( 0 ); int pos( 0 ); KTextEditor::Document *doc = view->document(); QRegExp re( "\\b(" + doc->text( range ) + "\\w{1,})" ); QString s, m; QSet<QString> seen; while( i < doc->lines() ) { s = doc->line( i ); pos = 0; while ( pos >= 0 ) { pos = re.indexIn( s, pos ); if ( pos >= 0 ) { // typing in the middle of a word if ( ! ( i == range.start().line() && pos == range.start().column() ) ) { m = re.cap( 1 ); if ( ! seen.contains( m ) ) { seen.insert( m ); l << m; } } pos += re.matchedLength(); } } i++; } return l; }
// Scan throughout the entire document for possible completions, // ignoring any dublets const QStringList KateNewCompletionModel::allMatches( KTextEditor::View *view, const KTextEditor::Range &range ) const { KTextEditor::Document *doc = view->document(); QString match_str = doc->text(range); QString s, m; QSet<QString> seen; QStringList l; int i( 0 ); int pos( 0 ); QRegExp class_rek("([A-Z]\\w*<( |\\w|,|<|>)+>)"); if (match_str.startsWith("new ")) { QString class_name = match_str.mid(4); for (i = 0; i < doc->lines(); ++i) { QString s = doc->line(i); QString m; pos = 0; while (pos >= 0) { pos = class_rek.indexIn(s, pos); if ( pos >= 0 ) { // typing in the middle of a word if ( ! ( i == range.start().line() && pos >= range.start().column() && pos <= range.end().column()) ) { m = class_rek.cap( 1 ); if ( ! seen.contains( m ) && m.startsWith(class_name)) { seen.insert( m ); m = "new " + m; l << m; } } pos += class_rek.matchedLength(); } } } } // convert yieldXXX and Ent::load('XXX') to genXXX and getXXX if (match_str.startsWith("gen") || match_str.startsWith("get")) { QString x = match_str.mid(3); class_rek = QRegExp("(yield|Ent::load\\(\\\'|Ent::load\\(\\\")([A-Z]\\w*)"); for (i = 0; i < doc->lines(); ++i) { QString s = doc->line(i); QString m; pos = 0; while (pos >= 0) { pos = class_rek.indexIn(s, pos); if ( pos >= 0 ) { // typing in the middle of a word if ( ! ( i == range.start().line() && pos >= range.start().column() && pos <= range.end().column()) ) { m = class_rek.cap( 2 ); if ( ! seen.contains( m ) && m.startsWith(x)) { seen.insert( m ); l << ("gen" + m); l << ("get" + m); } } pos += class_rek.matchedLength(); } } } } return l; }
void ReplaceMatches::doReplaceNextMatch() { if ((!m_manager) || (m_cancelReplace) || (m_tree->topLevelItemCount() != 1)) { m_rootIndex = -1; emit replaceDone(); return; } // NOTE The document managers signal documentWillBeDeleted() must be connected to // cancelReplace(). A closed file could lead to a crash if it is not handled. // Open the file QTreeWidgetItem *rootItem = m_tree->topLevelItem(0)->child(m_rootIndex); if (!rootItem) { m_rootIndex = -1; emit replaceDone(); return; } if (!rootItem->data(0, ColumnRole).toString().isEmpty()) { // this is a search as you type replace rootItem = m_tree->topLevelItem(0); m_cancelReplace = true; // only one document... } if (rootItem->checkState(0) == Qt::Unchecked) { m_rootIndex++; emit replaceNextMatch(); return; } KTextEditor::Document *doc; QString docUrl = rootItem->data(0, FileUrlRole).toString(); QString docName = rootItem->data(0, FileNameRole).toString(); if (docUrl.isEmpty()) { doc = findNamed(rootItem->data(0, FileNameRole).toString()); } else { doc = m_manager->findUrl(QUrl::fromUserInput(docUrl)); if (!doc) { doc = m_manager->openUrl(QUrl::fromUserInput(rootItem->data(0, FileUrlRole).toString())); } } if (!doc) { m_rootIndex++; emit replaceNextMatch(); return; } QVector<KTextEditor::MovingRange*> rVector; QStringList rTexts; KTextEditor::MovingInterface* miface = qobject_cast<KTextEditor::MovingInterface*>(doc); int line; int column; int matchLen; int endLine; int endColumn; QTreeWidgetItem *item; QString matchLines; // lines might be modified so search the document again for (int i=0; i<rootItem->childCount(); i++) { item = rootItem->child(i); if (item->checkState(0) == Qt::Unchecked) continue; line = endLine= item->data(0, LineRole).toInt(); column = item->data(0, ColumnRole).toInt(); matchLen = item->data(0, MatchLenRole).toInt(); matchLines = doc->line(line).mid(column); while (matchLines.size() < matchLen) { if (endLine+1 >= doc->lines()) break; endLine++; matchLines+= QLatin1Char('\n') + doc->line(endLine); } QRegularExpressionMatch match = m_regExp.match(matchLines); if (match.capturedStart() != 0) { qDebug() << matchLines << "Does not match" << m_regExp.pattern(); continue; } QString replaceText = m_replaceText; replaceText.replace(QStringLiteral("\\\\"), QStringLiteral("¤Search&Replace¤")); // allow captures \0 .. \9 for (int j = qMin(9, match.lastCapturedIndex()); j >= 0; --j) { replaceText.replace(QString(QStringLiteral("\\%1")).arg(j), match.captured(j)); } // allow captures \{0} .. \{9999999}... for (int j = match.lastCapturedIndex(); j >= 0; --j) { replaceText.replace(QString(QStringLiteral("\\{%1}")).arg(j), match.captured(j)); } replaceText.replace(QStringLiteral("\\n"), QStringLiteral("\n")); replaceText.replace(QStringLiteral("\\t"), QStringLiteral("\t")); replaceText.replace(QStringLiteral("¤Search&Replace¤"), QStringLiteral("\\")); rTexts << replaceText; replaceText.replace(QLatin1Char('\n'), QStringLiteral("\\n")); replaceText.replace(QLatin1Char('\t'), QStringLiteral("\\t")); QString html = item->data(0, PreMatchRole).toString(); html += QStringLiteral("<i><s>") + item->data(0, MatchRole).toString() + QStringLiteral("</s></i> "); html += QStringLiteral("<b>") + replaceText + QStringLiteral("</b>"); html += item->data(0, PostMatchRole).toString(); item->setData(0, Qt::DisplayRole, i18n("Line: <b>%1</b>: %2",line+1, html)); endLine = line; endColumn = column+matchLen; while ((endLine < doc->lines()) && (endColumn > doc->line(endLine).size())) { endColumn -= doc->line(endLine).size(); endColumn--; // remove one for '\n' endLine++; } KTextEditor::Range range(line, column, endLine, endColumn); KTextEditor::MovingRange* mr = miface->newMovingRange(range); rVector.append(mr); } for (int i=0; i<rVector.size(); i++) { line = rVector[i]->start().line(); column = rVector[i]->start().column(); doc->replaceText(*rVector[i], rTexts[i]); emit matchReplaced(doc, line, column, rTexts[i].length()); } qDeleteAll(rVector); m_rootIndex++; emit replaceNextMatch(); }
void KatePluginSymbolViewerView::parsePythonSymbols(void) { if (!m_mainWindow->activeView()) return; m_macro->setText(i18n("Show Globals")); m_struct->setText(i18n("Show Methods")); m_func->setText(i18n("Show Classes")); QString cl; // Current Line QPixmap cls( ( const char** ) class_xpm ); QPixmap mtd( ( const char** ) method_xpm ); QPixmap mcr( ( const char** ) macro_xpm ); int in_class = 0, state = 0, j; QString name; QTreeWidgetItem *node = NULL; QTreeWidgetItem *mcrNode = NULL, *mtdNode = NULL, *clsNode = NULL; QTreeWidgetItem *lastMcrNode = NULL, *lastMtdNode = NULL, *lastClsNode = NULL; KTextEditor::Document *kv = m_mainWindow->activeView()->document(); //kdDebug(13000)<<"Lines counted :"<<kv->numLines()<<endl; if(m_plugin->treeOn) { clsNode = new QTreeWidgetItem(m_symbols, QStringList( i18n("Classes") ) ); mcrNode = new QTreeWidgetItem(m_symbols, QStringList( i18n("Globals") ) ); mcrNode->setIcon(0, QIcon(mcr)); clsNode->setIcon(0, QIcon(cls)); if (m_plugin->expandedOn) { m_symbols->expandItem(mcrNode); m_symbols->expandItem(clsNode); } lastClsNode = clsNode; lastMcrNode = mcrNode; mtdNode = clsNode; lastMtdNode = clsNode; m_symbols->setRootIsDecorated(1); } else m_symbols->setRootIsDecorated(0); for (int i=0; i<kv->lines(); i++) { int line=i; cl = kv->line(i); // concatenate continued lines and remove continuation marker if (cl.length()==0) continue; while (cl[cl.length()-1]==QLatin1Char('\\')) { cl=cl.left(cl.length()-1); i++; if (i<kv->lines()) cl+=kv->line(i); else break; } if(cl.indexOf( QRegExp(QLatin1String("^class [a-zA-Z0-9_,\\s\\(\\).]+:")) ) >= 0) in_class = 1; //if(cl.find( QRegExp(QLatin1String("[\\s]+def [a-zA-Z_]+[^#]*:")) ) >= 0) in_class = 2; if(cl.indexOf( QRegExp(QLatin1String("^def\\s+[a-zA-Z_]+[^#]*:")) ) >= 0 ) in_class = 0; if (cl.indexOf(QLatin1String("def ")) >= 0 || (cl.indexOf(QLatin1String("class ")) >= 0 && in_class == 1)) { if (cl.indexOf(QLatin1String("def ")) >= 0 && in_class == 1) in_class = 2; state = 1; if (cl.indexOf(QLatin1Char(':')) >= 0) state = 3; // found in the same line. Done else if (cl.indexOf(QLatin1Char('(')) >= 0) state = 2; if (state == 2 || state == 3) name = cl.left (cl.indexOf (QLatin1Char('('))); } if (state > 0 && state < 3) { for (j = 0; j < cl.length(); j++) { if (cl.at(j) == QLatin1Char('(')) state = 2; else if (cl.at(j) == QLatin1Char(':')) { state = 3; break; } if (state == 1) name += cl.at(j); } } if (state == 3) { //qDebug(13000)<<"Function -- Inserted : "<<name<<" at row : "<<i; if (in_class == 1) //strip off the word "class " name = name.trimmed ().mid (6); else //strip off the word "def " name = name.trimmed ().mid (4); if (func_on == true && in_class == 1) { if (m_plugin->treeOn) { node = new QTreeWidgetItem(clsNode, lastClsNode); if (m_plugin->expandedOn) m_symbols->expandItem(node); lastClsNode = node; mtdNode = lastClsNode; lastMtdNode = lastClsNode; } else node = new QTreeWidgetItem(m_symbols); node->setText(0, name); node->setIcon(0, QIcon(cls)); node->setText(1, QString::number( line, 10)); } if (struct_on == true && in_class == 2) { if (m_plugin->treeOn) { node = new QTreeWidgetItem(mtdNode, lastMtdNode); lastMtdNode = node; } else node = new QTreeWidgetItem(m_symbols); node->setText(0, name); node->setIcon(0, QIcon(mtd)); node->setText(1, QString::number( line, 10)); } if (macro_on == true && in_class == 0) { if (m_plugin->treeOn) { node = new QTreeWidgetItem(mcrNode, lastMcrNode); lastMcrNode = node; } else node = new QTreeWidgetItem(m_symbols); node->setText(0, name); node->setIcon(0, QIcon(mcr)); node->setText(1, QString::number( line, 10)); } state = 0; name.clear(); } } }
void KatePluginSymbolViewerView::parseFortranSymbols(void) { if (!mainWindow()->activeView()) return; QString currline; QString subrStr("subroutine "); QString funcStr("function "); QString modStr("module "); QString stripped=""; int i; int fnd,block=0,blockend=0,paro=0,parc=0; bool mainprog; QTreeWidgetItem *node = NULL; QTreeWidgetItem *subrNode = NULL, *funcNode = NULL, *modNode = NULL; QTreeWidgetItem *lastSubrNode = NULL, *lastFuncNode = NULL, *lastModNode = NULL; QPixmap func( ( const char** ) class_xpm ); QPixmap subr( ( const char** ) macro_xpm ); QPixmap mod( ( const char** ) struct_xpm ); //It is necessary to change names m_macro->setText(i18n("Show Subroutines")); m_struct->setText(i18n("Show Modules")); m_func->setText(i18n("Show Functions")); if(m_plugin->treeOn) { funcNode = new QTreeWidgetItem(m_symbols, QStringList(i18n("Functions") ) ); subrNode = new QTreeWidgetItem(m_symbols, QStringList( i18n("Subroutines") ) ); modNode = new QTreeWidgetItem(m_symbols, QStringList( i18n("Modules") ) ); funcNode->setIcon(0, QIcon(func)); modNode->setIcon(0, QIcon(mod)); subrNode->setIcon(0, QIcon(subr)); if (m_plugin->expandedOn) { m_symbols->expandItem(funcNode); m_symbols->expandItem(subrNode); m_symbols->expandItem(modNode); } lastSubrNode = subrNode; lastFuncNode = funcNode; lastModNode = modNode; m_symbols->setRootIsDecorated(1); } else m_symbols->setRootIsDecorated(0); KTextEditor::Document *kDoc = mainWindow()->activeView()->document(); for (i = 0; i < kDoc->lines(); i++) { currline = kDoc->line(i); currline = currline.trimmed(); //currline = currline.simplified(); is this really needed ? //Fortran is case insensitive currline = currline.toLower(); bool comment = false; //kdDebug(13000)<<currline<<endl; if(currline == "") continue; if(currline.at(0) == '!' || currline.at(0) == 'c') comment = true; //block=0; mainprog=false; if(!comment) { //Subroutines if(currline.startsWith(subrStr) || currline.startsWith("program ")) { block=1; stripped=""; } //Modules else if(currline.startsWith(modStr)) { block=2; stripped=""; } //Functions else if(((( currline.startsWith("real") || currline.startsWith("double") || currline.startsWith("integer") || currline.startsWith("character")) || currline.startsWith("logical") || currline.startsWith("pure") || currline.startsWith("elemental") || currline.startsWith("recursive") || currline.startsWith("type")) && currline.indexOf(funcStr) > 0) || currline.startsWith(funcStr) ) { block=3; stripped=""; } //Subroutines if(block==1) { if(currline.startsWith("program ")) mainprog=true; if (macro_on == true) // not really a macro, but a subroutines { stripped += currline.right(currline.length()); stripped = stripped.simplified(); stripped.remove('*'); stripped.remove('+'); stripped.remove('$'); if(blockend==0) { fnd = stripped.indexOf(' '); stripped = currline.right(currline.length()-fnd-1); } stripped.remove(' '); fnd = stripped.indexOf('!'); if(fnd>0) { stripped = stripped.left(fnd); } paro+=currline.count(')', Qt::CaseSensitive); parc+=currline.count('(', Qt::CaseSensitive); if((paro==parc || mainprog) && stripped.endsWith('&', Qt::CaseInsensitive)==false) { stripped.remove('&'); if(mainprog && stripped.indexOf('(')<0 && stripped.indexOf(')')<0) stripped.prepend("Main: "); if(stripped.indexOf('=')==-1) { if (m_plugin->treeOn) { node = new QTreeWidgetItem(subrNode, lastSubrNode); lastSubrNode = node; } else node = new QTreeWidgetItem(m_symbols); node->setText(0, stripped); node->setIcon(0, QIcon(subr)); node->setText(1, QString::number( i, 10)); } stripped=""; block=0; blockend=0; paro=0; parc=0; } else { blockend=1; } } } //Modules else if(block==2) { if (struct_on == true) // not really a struct, but a module { stripped = currline.right(currline.length()); stripped = stripped.simplified(); fnd = stripped.indexOf(' '); stripped = currline.right(currline.length()-fnd-1); fnd = stripped.indexOf('!'); if(fnd>0) { stripped = stripped.left(fnd); } if(stripped.indexOf('=')==-1) { if (m_plugin->treeOn) { node = new QTreeWidgetItem(modNode, lastModNode); lastModNode = node; } else node = new QTreeWidgetItem(m_symbols); node->setText(0, stripped); node->setIcon(0, QIcon(mod)); node->setText(1, QString::number( i, 10)); } stripped = ""; } block=0; blockend=0; } //Functions else if(block==3) { if (func_on == true) { stripped += currline.right(currline.length()); stripped = stripped.trimmed(); stripped.remove( "function" ); stripped.remove('*'); stripped.remove('+'); stripped.remove('$'); stripped = stripped.simplified(); fnd = stripped.indexOf('!'); if(fnd>0) { stripped = stripped.left(fnd); } stripped = stripped.trimmed(); paro+=currline.count(')', Qt::CaseSensitive); parc+=currline.count('(', Qt::CaseSensitive); if(paro==parc && stripped.endsWith('&')==false) { stripped.remove('&'); if (m_plugin->treeOn) { node = new QTreeWidgetItem(funcNode, lastFuncNode); lastFuncNode = node; } else node = new QTreeWidgetItem(m_symbols); node->setText(0, stripped); node->setIcon(0, QIcon(func)); node->setText(1, QString::number( i, 10)); stripped = ""; block=0; paro=0; parc=0; } blockend=0; } } } } //for i loop }
void KatePluginSymbolViewerView::parseXsltSymbols(void) { if (!win->activeView()) return; popup->changeItem( popup->idAt(2),i18n("Show Params")); popup->changeItem( popup->idAt(3),i18n("Show Variables")); popup->changeItem( popup->idAt(4),i18n("Show Templates")); QString cl; // Current Line QString stripped; char comment = 0; char templ = 0; int i; QPixmap cls( ( const char** ) class_xpm ); QPixmap sct( ( const char** ) struct_xpm ); QPixmap mcr( ( const char** ) macro_xpm ); QPixmap cls_int( ( const char** ) class_int_xpm ); QTreeWidgetItem *node = NULL; QTreeWidgetItem *mcrNode = NULL, *sctNode = NULL, *clsNode = NULL; QTreeWidgetItem *lastMcrNode = NULL, *lastSctNode = NULL, *lastClsNode = NULL; KTextEditor::Document *kv = win->activeView()->document(); //kdDebug(13000)<<"Lines counted :"<<kv->numLines()<<endl; if(treeMode) { mcrNode = new QTreeWidgetItem(symbols, QStringList( i18n("Params") ) ); sctNode = new QTreeWidgetItem(symbols, QStringList( i18n("Variables") ) ); clsNode = new QTreeWidgetItem(symbols, QStringList( i18n("Templates") ) ); mcrNode->setIcon(0, QIcon(mcr)); sctNode->setIcon(0, QIcon(sct)); clsNode->setIcon(0, QIcon(cls)); if (expanded_on) { symbols->expandItem(mcrNode); symbols->expandItem(sctNode); symbols->expandItem(clsNode); } lastMcrNode = mcrNode; lastSctNode = sctNode; lastClsNode = clsNode; symbols->setRootIsDecorated(1); } else { symbols->setRootIsDecorated(0); } for (i=0; i<kv->lines(); i++) { cl = kv->line(i); cl = cl.trimmed(); if(cl.indexOf(QRegExp("<!--")) >= 0) { comment = 1; } if(cl.indexOf(QRegExp("-->")) >= 0) { comment = 0; continue; } if(cl.indexOf(QRegExp("^</xsl:template>")) >= 0) { templ = 0; continue; } if (comment==1) { continue; } if (templ==1) { continue; } if(cl.indexOf(QRegExp("^<xsl:param ")) == 0 && macro_on) { QString stripped = cl.remove(QRegExp("^<xsl:param +name=\"")); stripped = stripped.remove(QRegExp("\".*")); if (treeMode) { node = new QTreeWidgetItem(mcrNode, lastMcrNode); lastMcrNode = node; } else node = new QTreeWidgetItem(symbols); node->setText(0, stripped); node->setIcon(0, QIcon(mcr)); node->setText(1, QString::number( i, 10)); } if(cl.indexOf(QRegExp("^<xsl:variable ")) == 0 && struct_on) { QString stripped = cl.remove(QRegExp("^<xsl:variable +name=\"")); stripped = stripped.remove(QRegExp("\".*")); if (treeMode) { node = new QTreeWidgetItem(sctNode, lastSctNode); lastSctNode = node; } else node = new QTreeWidgetItem(symbols); node->setText(0, stripped); node->setIcon(0, QIcon(sct)); node->setText(1, QString::number( i, 10)); } if(cl.indexOf(QRegExp("^<xsl:template +match=")) == 0 && func_on) { QString stripped = cl.remove(QRegExp("^<xsl:template +match=\"")); stripped = stripped.remove(QRegExp("\".*")); if (treeMode) { node = new QTreeWidgetItem(clsNode, lastClsNode); lastClsNode = node; } else node = new QTreeWidgetItem(symbols); node->setText(0, stripped); node->setIcon(0, QIcon(cls_int)); node->setText(1, QString::number( i, 10)); } if(cl.indexOf(QRegExp("^<xsl:template +name=")) == 0 && func_on) { QString stripped = cl.remove(QRegExp("^<xsl:template +name=\"")); stripped = stripped.remove(QRegExp("\".*")); if (treeMode) { node = new QTreeWidgetItem(clsNode, lastClsNode); lastClsNode = node; } else node = new QTreeWidgetItem(symbols); node->setText(0, stripped); node->setIcon(0, QIcon(cls)); node->setText(1, QString::number( i, 10)); } if(cl.indexOf(QRegExp("<xsl:template")) >= 0) { templ = 1; } } }
void KatePluginSymbolViewerView::parseEcmaSymbols(void) { // make sure there is an active view to attach to if (!mainWindow()->activeView()) return; // the current line QString cl; // the current line stripped of all comments and strings QString stripped; // a parsed class/function identifier QString identifier; // temporary characters QChar current, next, string_start = '\0'; // whether we are in a multiline comment bool in_comment = false; // the current line index int line = 0; // indices into the string int c, function_start = 0; // the current depth of curly brace encapsulation int brace_depth = 0; // a list of inserted nodes with the index being the brace depth at insertion QList<QTreeWidgetItem *> nodes; QPixmap cls( ( const char** ) class_xpm ); QPixmap mtd( ( const char** ) method_xpm ); QTreeWidgetItem *node = NULL; if (m_plugin->treeOn) { m_symbols->setRootIsDecorated(1); } else { m_symbols->setRootIsDecorated(0); } // read the document line by line KTextEditor::Document *kv = mainWindow()->activeView()->document(); for (line=0; line < kv->lines(); line++) { // get a line to process, trimming off whitespace cl = kv->line(line); cl = cl.trimmed(); stripped = ""; bool in_string = false; for (c = 0; c < cl.length(); c++) { // get the current character and the next current = cl.at(c); if ((c+1) < cl.length()) next = cl.at(c+1); else next = '\0'; // skip the rest of the line if we find a line comment if ((! in_comment) && (current == '/') && (next == '/')) break; // open/close multiline comments if ((! in_string) && (current == '/') && (next == '*')) { in_comment = true; c++; continue; } else if ((in_comment) && (current == '*') && (next == '/')) { in_comment = false; c++; continue; } // open strings if ((! in_comment) && (! in_string)) { if ((current == '\'') || (current == '"')) { string_start = current; in_string = true; continue; } } // close strings if (in_string) { // skip escaped backslashes if ((current == '\\') && (next == '\\')) { c++; continue; } // skip escaped string closures if ((current == '\\') && (next == string_start)) { c++; continue; } else if (current == string_start) { in_string = false; continue; } } // add anything outside strings and comments to the stripped line if ((! in_comment) && (! in_string)) { stripped += current; } } // scan the stripped line for (c = 0; c < stripped.length(); c++) { current = stripped.at(c); // look for class definitions (for ActionScript) if ((current == 'c') && (stripped.indexOf("class", c) == c)) { identifier = ""; c += 6; for (c = c; c < stripped.length(); c++) { current = stripped.at(c); // look for the beginning of the class itself if ((current == '(') || (current == '{')) { c--; break; } else { identifier += current; } } // trim whitespace identifier = identifier.trimmed(); // get the node to add the class entry to if ((m_plugin->treeOn) && (! nodes.isEmpty())) { node = new QTreeWidgetItem(nodes.last()); if (m_plugin->expandedOn) m_symbols->expandItem(node); } else { node = new QTreeWidgetItem(m_symbols); } // add an entry for the class node->setText(0, identifier); node->setIcon(0, QIcon(cls)); node->setText(1, QString::number(line, 10)); if (m_plugin->expandedOn) m_symbols->expandItem(node); } // (look for classes) // look for function definitions if ((current == 'f') && (stripped.indexOf("function", c) == c)) { function_start = c; c += 8; // look for the beginning of the parameters identifier = ""; for (c = c; c < stripped.length(); c++) { current = stripped.at(c); // look for the beginning of the function definition if ((current == '(') || (current == '{')) { c--; break; } else { identifier += current; } } // trim off whitespace identifier = identifier.trimmed(); // if we have an anonymous function, back up to see if it's assigned to anything if (! (identifier.length() > 0)) { QChar ch = '\0'; for (int end = function_start - 1; end >= 0; end--) { ch = stripped.at(end); // skip whitespace if ((ch == ' ') || (ch == '\t')) continue; // if we hit an assignment or object property operator, // get the preceding identifier if ((ch == '=') || (ch == ':')) { end--; while (end >= 0) { ch = stripped.at(end); if ((ch != ' ') && (ch != '\t')) break; end--; } int start = end; while (start >= 0) { ch = stripped.at(start); if (((ch >= 'a') && (ch <= 'z')) || ((ch >= 'A') && (ch <= 'Z')) || ((ch >= '0') && (ch <= '9')) || (ch == '_')) start--; else { start++; break; } } identifier = stripped.mid(start, (end - start) + 1); break; } // if we hit something else, we're not going to be able // to read an assignment identifier else break; } } // if we have a function identifier, make a node if (identifier.length() > 0) { // make a node for the function QTreeWidgetItem *parent = NULL; if (! nodes.isEmpty()) { parent = nodes.last(); } if ((m_plugin->treeOn) && (parent != NULL)) node = new QTreeWidgetItem(parent); else node = new QTreeWidgetItem(m_symbols); // mark the parent as a class (if it's not the root level) if (parent != NULL) { parent->setIcon(0, QIcon(cls)); // mark this function as a method of the parent node->setIcon(0, QIcon(mtd)); } // mark root-level functions as classes else { node->setIcon(0, QIcon(cls)); } // add the function node->setText(0, identifier); node->setText(1, QString::number(line, 10)); if (m_plugin->expandedOn) m_symbols->expandItem(node); } } // (look for functions) // keep track of brace depth if (current == '{') { brace_depth++; // if a node has been added at this level or above, // use it to extend the stack if (node != NULL) nodes.append(node); // if no node has been added, extend the last node to this depth else if (! nodes.isEmpty()) nodes.append(nodes.last()); } else if (current == '}') { brace_depth--; // pop the last node off the stack node = NULL; if (! nodes.isEmpty()) nodes.removeLast(); } } // (scan the stripped line) } // (iterate through lines of the document) }
// Do one completion, searching in the desired direction, // if possible void KateWordCompletionView::complete( bool fw ) { KTextEditor::Range r = range(); int inc = fw ? 1 : -1; KTextEditor::Document *doc = m_view->document(); if ( d->dcRange.isValid() ) { //kDebug( 13040 )<<"CONTINUE "<<d->dcRange; // this is a repeted activation // if we are back to where we started, reset. if ( ( fw && d->directionalPos == -1 ) || ( !fw && d->directionalPos == 1 ) ) { const int spansColumns = d->liRange->end().column() - d->liRange->start().column(); if ( spansColumns > 0 ) doc->removeText( *d->liRange ); d->liRange->setRange( KTextEditor::Range::invalid() ); d->dcCursor = r.end(); d->directionalPos = 0; return; } if ( fw ) { const int spansColumns = d->liRange->end().column() - d->liRange->start().column(); d->dcCursor.setColumn( d->dcCursor.column() + spansColumns ); } d->directionalPos += inc; } else // new completion, reset all { //kDebug( 13040 )<<"RESET FOR NEW"; d->dcRange = r; d->liRange->setRange( KTextEditor::Range::invalid() ); d->dcCursor = r.start(); d->directionalPos = inc; d->liRange->setView( m_view ); connect( m_view, SIGNAL(cursorPositionChanged(KTextEditor::View*,KTextEditor::Cursor)), this, SLOT(slotCursorMoved()) ); } d->re.setPattern( "\\b" + doc->text( d->dcRange ) + "(\\w+)" ); int pos ( 0 ); QString ln = doc->line( d->dcCursor.line() ); while ( true ) { //kDebug( 13040 )<<"SEARCHING FOR "<<d->re.pattern()<<" "<<ln<<" at "<<d->dcCursor; pos = fw ? d->re.indexIn( ln, d->dcCursor.column() ) : d->re.lastIndexIn( ln, d->dcCursor.column() ); if ( pos > -1 ) // we matched a word { //kDebug( 13040 )<<"USABLE MATCH"; QString m = d->re.cap( 1 ); if ( m != doc->text( *d->liRange ) && (d->dcCursor.line() != d->dcRange.start().line() || pos != d->dcRange.start().column() ) ) { // we got good a match! replace text and return. d->isCompleting = true; KTextEditor::Range replaceRange(d->liRange->toRange()); if (!replaceRange.isValid()) { replaceRange.setRange(r.end(), r.end()); } doc->replaceText( replaceRange, m ); d->liRange->setRange( KTextEditor::Range( d->dcRange.end(), m.length() ) ); d->dcCursor.setColumn( pos ); // for next try d->isCompleting = false; return; } // equal to last one, continue else { //kDebug( 13040 )<<"SKIPPING, EQUAL MATCH"; d->dcCursor.setColumn( pos ); // for next try if ( fw ) d->dcCursor.setColumn( pos + m.length() ); else { if ( pos == 0 ) { if ( d->dcCursor.line() > 0 ) { int l = d->dcCursor.line() + inc; ln = doc->line( l ); d->dcCursor.setPosition( l, ln.length() ); } else { KNotification::beep(); return; } } else d->dcCursor.setColumn( d->dcCursor.column()-1 ); } } } else // no match { //kDebug( 13040 )<<"NO MATCH"; if ( (! fw && d->dcCursor.line() == 0 ) || ( fw && d->dcCursor.line() >= doc->lines() ) ) { KNotification::beep(); return; } int l = d->dcCursor.line() + inc; ln = doc->line( l ); d->dcCursor.setPosition( l, fw ? 0 : ln.length() ); } } // while true }
void KatePluginSymbolViewerView::parseBashSymbols(void) { if (!mainWindow()->activeView()) return; QString currline; QString funcStr("function "); int i; //bool mainprog; QTreeWidgetItem *node = NULL; QTreeWidgetItem *funcNode = NULL; QTreeWidgetItem *lastFuncNode = NULL; QPixmap func( ( const char** ) class_xpm ); //It is necessary to change names m_func->setText(i18n("Show Functions")); if(m_plugin->treeOn) { funcNode = new QTreeWidgetItem(m_symbols, QStringList(i18n("Functions") ) ); funcNode->setIcon(0, QIcon(func)); if (m_plugin->expandedOn) { m_symbols->expandItem(funcNode); } lastFuncNode = funcNode; m_symbols->setRootIsDecorated(1); } else m_symbols->setRootIsDecorated(0); KTextEditor::Document *kDoc = mainWindow()->activeView()->document(); for (i = 0; i < kDoc->lines(); i++) { currline = kDoc->line(i); currline = currline.trimmed(); currline = currline.simplified(); bool comment = false; //kDebug(13000)<<currline<<endl; if(currline == "") continue; if(currline.at(0) == '#') comment = true; //mainprog=false; if(!comment && func_on) { QString funcName; // skip line if no function defined // note: function name must match regex: [a-zA-Z0-9-_]+ if(!currline.contains(QRegExp("^(function )*[a-zA-Z0-9-_]+ *\\( *\\)")) && !currline.contains(QRegExp("^function [a-zA-Z0-9-_]+"))) continue; // strip everything unneeded and get the function's name currline.remove(QRegExp("^(function )*")); funcName = currline.split(QRegExp("((\\( *\\))|[^a-zA-Z0-9-_])"))[0].simplified(); if(!funcName.size()) continue; funcName.append("()"); if (m_plugin->treeOn) { node = new QTreeWidgetItem(funcNode, lastFuncNode); lastFuncNode = node; } else node = new QTreeWidgetItem(m_symbols); node->setText(0, funcName); node->setIcon(0, QIcon(func)); node->setText(1, QString::number( i, 10)); } } //for i loop }