Esempio n. 1
0
// 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;
  }
Esempio n. 2
0
void KeywordItem::execute(KTextEditor::View* view, const KTextEditor::Range& word)
{
    KTextEditor::Document *document = view->document();
    if ( !m_replacement.isEmpty() ) {
        QString replacement = m_replacement;
        replacement = replacement.replace('\n', '\n' + getIndendation(document->line(word.start().line())));
        replacement = replacement.replace(QLatin1String("%INDENT%"), indentString(document));

        int cursorPos = replacement.indexOf(QStringLiteral("%CURSOR%"));
        int selectionEnd = -1;
        if ( cursorPos != -1 ) {
            replacement.remove(QStringLiteral("%CURSOR%"));
        } else {
            cursorPos = replacement.indexOf(QStringLiteral("%SELECT%"));
            if ( cursorPos != -1 ) {
                replacement.remove(QStringLiteral("%SELECT%"));
                selectionEnd = replacement.indexOf(QStringLiteral("%ENDSELECT%"), cursorPos + 1);
                if ( selectionEnd == -1 ) {
                    selectionEnd = replacement.length();
                }
                replacement.remove(QStringLiteral("%ENDSELECT%"));
            }
        }

        document->replaceText(word, replacement);

        if ( cursorPos != -1 ) {
            if (view) {
                replacement = replacement.left(cursorPos);
                KTextEditor::Cursor newPos(
                    word.start().line() + replacement.count('\n'),
                    word.start().column() + replacement.length() - replacement.lastIndexOf('\n') - 1
                );
                view->setCursorPosition(newPos);
                if ( selectionEnd != -1 ) {
                    ///TODO: maybe we want to support multi-line selections in the future?
                    view->setSelection(
                        KTextEditor::Range(
                            newPos,
                            KTextEditor::Cursor(
                                newPos.line(),
                                newPos.column() + selectionEnd - cursorPos
                            )
                        )
                    );
                }
            }
        }
    } else {
        document->replaceText(word, m_keyword + ' ');
    }
}
Esempio n. 3
0
// ### 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();
}
Esempio n. 4
0
// 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;
}
Esempio n. 5
0
// 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;
}
Esempio n. 6
0
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();
}
Esempio n. 7
0
void ImplementationItem::execute(KTextEditor::View* view, const KTextEditor::Range& word)
{
    DUChainReadLocker lock(DUChain::lock());
    KTextEditor::Document *document = view->document();

    QString replText;

    if (m_declaration) {
        //TODO:respect custom code styles

        // get existing modifiers so we can respect the user's choice of public/protected and final
        QStringList modifiers = getMethodTokens(document->text(KTextEditor::Range(KTextEditor::Cursor::start(), word.start())));
        // get range to replace
        KTextEditor::Range replaceRange(word);
        if (!modifiers.isEmpty()) {
            // TODO: is there no easy API to map QString Index to a KTextEditor::Cursor ?!
            QString methodText = document->text(KTextEditor::Range(KTextEditor::Cursor::start(), word.start()));
            methodText = methodText.left(methodText.lastIndexOf(modifiers.last(), -1, Qt::CaseInsensitive));
            replaceRange.start() = KTextEditor::Cursor(methodText.count('\n'), methodText.length() - methodText.lastIndexOf('\n') - 1);
        }

        // get indendation
        QString indendation;
        {
            QString currentLine = document->line(replaceRange.start().line());
            indendation = getIndendation(currentLine);

            if ( !currentLine.isEmpty() && currentLine != indendation ) {
                // since theres some non-whitespace in this line, skip to the enxt one
                replText += '\n' + indendation;
            }

            if (indendation.isEmpty()) {
                // use a minimal indendation
                // TODO: respect code style
                indendation = QStringLiteral("  ");
                replText += indendation;
            }
        }

        #if 0
        //Disabled, because not everyone writes phpdoc for every function
        //TODO: move to a phpdoc helper
        // build phpdoc comment
        {
            QualifiedIdentifier parentClassIdentifier;
            if (DUContext* pctx = m_declaration->context()) {
                parentClassIdentifier = pctx->localScopeIdentifier();
            } else {
                qCDebug(COMPLETION) << "completion item for implementation has no parent context!";
            }

            replText += "/**\n" + indendation + " * ";
            // insert old comment:
            const QString indentationWithExtra = "\n" + indendation + " *";
            replText += m_declaration->comment().replace('\n', indentationWithExtra.toAscii().constData());
            replText += "\n" + indendation + " * @overload " + m_declaration->internalContext()->scopeIdentifier(true).toString();
            replText += "\n" + indendation + " **/\n" + indendation;
        }
        #endif

        // write function signature

        // copy existing modifiers
        if (!modifiers.isEmpty()) {
            // the tokens are in a bad order and there's no reverse method or similar, so we can't simply join the tokens
            QStringList::const_iterator i = modifiers.constEnd() - 1;
            while (true) {
                replText += (*i) + ' ';
                if (i == modifiers.constBegin()) {
                    break;
                } else {
                    --i;
                }
            }
        }

        QString functionName;
        bool isConstructorOrDestructor = false;
        bool isInterface = false;

        if (ClassMemberDeclaration* member = dynamic_cast<ClassMemberDeclaration*>(m_declaration.data())) {
            // NOTE: it should _never_ be private - but that's the completionmodel / context / worker's job
            if (!modifiers.contains(QStringLiteral("public")) && !modifiers.contains(QStringLiteral("protected"))) {
                if (member->accessPolicy() == Declaration::Protected) {
                    replText += QLatin1String("protected ");
                } else {
                    replText += QLatin1String("public ");
                }
            }
            if (!modifiers.contains(QStringLiteral("static")) && member->isStatic()) {
                replText += QLatin1String("static ");
            }
            functionName = member->identifier().toString();

            ClassMethodDeclaration* method = dynamic_cast<ClassMethodDeclaration*>(m_declaration.data());
            if (method) {
                functionName = method->prettyName().str();
                isConstructorOrDestructor = method->isConstructor() || method->isDestructor();
            }

            if (member->context() && member->context()->owner()) {
                ClassDeclaration* classDec = dynamic_cast<ClassDeclaration*>(member->context()->owner());
                if (classDec) {
                    isInterface = (classDec->classType() == ClassDeclarationData::Interface);
                }
            }
        } else {
            qCDebug(COMPLETION) << "completion item for implementation was not a classfunction declaration!";
            functionName = m_declaration->identifier().toString();
        }

        if (m_type == ImplementationItem::OverrideVar) {
            replText += "$" + functionName + " = ";
        } else {
            if (!modifiers.contains(QStringLiteral("function"))) {
                replText += QLatin1String("function ");
            }

            replText += functionName;

            {
                // get argument list
                QString arguments;
                createArgumentList(*this, arguments, 0, true);
                replText += arguments;
            }

            QString arguments;
            QVector<Declaration*> parameters;
            if (DUChainUtils::getArgumentContext(m_declaration.data()))
                parameters = DUChainUtils::getArgumentContext(m_declaration.data())->localDeclarations();
            arguments = '(';
            bool first = true;
            foreach(Declaration* dec, parameters) {
                if (first)
                    first = false;
                else
                    arguments += QLatin1String(", ");

                arguments += '$' + dec->identifier().toString();
            }
            arguments += ')';

            bool voidReturnType = false;
            if (FunctionType::Ptr::dynamicCast(m_declaration->abstractType())) {
                AbstractType::Ptr retType = FunctionType::Ptr::staticCast(m_declaration->abstractType())->returnType();
                if (retType->equals(new IntegralType(IntegralType::TypeVoid))) {
                    voidReturnType = true;
                }
            }

            replText += QStringLiteral("\n%1{\n%1    ").arg(indendation);
            if (isInterface || m_type == ImplementationItem::Implement) {
            } else if (!isConstructorOrDestructor && !voidReturnType) {
                replText += QStringLiteral("$ret = parent::%2%3;\n%1    return $ret;").arg(indendation, functionName, arguments);
            } else {
                replText += QStringLiteral("parent::%1%2;").arg(functionName, arguments);
            }
            replText += QStringLiteral("\n%1}\n%1")
                    .arg(indendation);

        }


        //TODO: properly place the cursor inside the {} part
        document->replaceText(replaceRange, replText);

    } else {
Esempio n. 8
0
void ReplaceMatches::doReplaceNextMatch()
{
    if ((!m_manager) || (m_cancelReplace)) {
        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(m_rootIndex);
    if (!rootItem) {
        m_rootIndex = -1;
        emit replaceDone();
        return;
    }

    if (rootItem->checkState(0) == Qt::Unchecked) {
        m_rootIndex++;
        emit replaceNextMatch();
        return;
    }

    KTextEditor::Document *doc = m_manager->findUrl(rootItem->data(0, Qt::UserRole).toString());
    if (!doc) {
        doc = m_manager->openUrl(rootItem->data(0, Qt::UserRole).toString());
    }

    if (!doc) {
        m_rootIndex++;
        emit replaceNextMatch();
        return;
    }

    QVector<KTextEditor::MovingRange*> rVector;
    KTextEditor::MovingInterface* miface = qobject_cast<KTextEditor::MovingInterface*>(doc);
    int line;
    int column;
    int len;
    QTreeWidgetItem *item;
    
    // 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 = item->data(1, Qt::UserRole).toInt();
        column = item->data(2, Qt::UserRole).toInt();
        len = item->data(3, Qt::UserRole).toInt();
        if (m_regExp.indexIn(doc->line(line), column) != column) {
            kDebug() << "expression does not match";
            continue;
        }
        QString html = item->data(1, Qt::ToolTipRole).toString();
        html += "<i><s>" + item->data(2, Qt::ToolTipRole).toString() + "</s></i> ";
        html += "<b>" + m_replaceText + "</b>";
        html += item->data(3, Qt::ToolTipRole).toString();
        item->setData(0, Qt::DisplayRole, QString("Line: <b>%1</b>: %2").arg(line+1).arg(html));
        KTextEditor::Range range(line, column, line, column+len);
        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], m_replaceText);
        emit matchReplaced(doc, line, column, m_replaceText.length());
    }

    qDeleteAll(rVector);

    m_rootIndex++;
    emit replaceNextMatch();
}
Esempio n. 9
0
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();
        }
    }

}
Esempio n. 10
0
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
}
Esempio n. 11
0
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;
       }
    }
}
Esempio n. 12
0
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)

}
Esempio n. 13
0
// 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
}
Esempio n. 14
0
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
}