diff --git a/share/samples/assistant-qt4.desktop b/share/samples/assistant-qt4.desktop deleted file mode 100644 index dd8fc65..0000000 --- a/share/samples/assistant-qt4.desktop +++ /dev/null @@ -1,89 +0,0 @@ -[Desktop Entry] -Categories=Qt;Development;Documentation; -Exec=/usr/bin/assistant-qt4 -Name=Qt 4 Assistant -GenericName=Document Browser -GenericName[af]=Dokument Blaaier -GenericName[az]=Sənəd Səyyahı -GenericName[bg]=Преглед на документи -GenericName[bn]=নথী ব্রাউজার -GenericName[br]=Furcher Teulioù -GenericName[bs]=Preglednik QT dokumenata -GenericName[ca]=Navegador de documents -GenericName[cs]=Prohlížeč dokumentace -GenericName[cy]=Porydd Dogfen -GenericName[da]=Dokumentfremviser -GenericName[de]=Dokumentbrowser -GenericName[el]=Προβολέας εγγράφων -GenericName[eo]=Dokumentorigardilo -GenericName[es]=Navegador de documentos -GenericName[et]=Dokumentatsiooni brauser -GenericName[eu]=Dokumentu Ikustailua -GenericName[fa]=مرورگر سند -GenericName[fi]=Asiakirjaselain -GenericName[fo]=Skjalakagari -GenericName[fr]=Explorateur de documentation Qt -GenericName[gl]=Explorador de Documentos -GenericName[he]=דפדפן מסמכים -GenericName[hi]=दस्तावेज़़ ब्राउज़र -GenericName[hr]=Preglednik dokumenata -GenericName[hu]=Dokumentumböngésző -GenericName[is]=Skjalavafri -GenericName[it]=Visualizzatore di documenti -GenericName[ja]=ドキュメントブラウザ -GenericName[km]=កម្មវិធី​រុករក​ឯកសារ -GenericName[ko]=문서 탐색기 -GenericName[lo]=ເຄື່ອງມືເລືອກເບິ່ງແຟ້ມເອກະສານ -GenericName[lt]=Dokumentų žiūriklis -GenericName[lv]=Dokumentu Pārlūks -GenericName[mn]=Баримтын хөтөч -GenericName[ms]=Pelungsur Dokumen -GenericName[mt]=Browser ta' Dokumenti -GenericName[nb]=Dokumentleser -GenericName[nds]=Dokmentkieker -GenericName[nl]=Documentbrowser -GenericName[nn]=Dokumentlesar -GenericName[nso]=Seinyakisi sa Tokomane -GenericName[pa]=ਦਸਤਾਵੇਜ਼ ਝਲਕਾਰਾ -GenericName[pl]=Przeglądarka dokumentów -GenericName[pt]=Navegador de Documentos -GenericName[pt_BR]=Navegador de Documentos -GenericName[ro]=Navigator de documente -GenericName[ru]=Программа просмотра документов -GenericName[se]=Dokumeantalogan -GenericName[sk]=Prehliadač dokumentácie -GenericName[sl]=Pregledovalnik dokumentov -GenericName[sr]=Претраживач докумената -GenericName[sr@Latn]=Pretraživač dokumenata -GenericName[ss]=Ibrawuza yelidokhumente -GenericName[sv]=Dokumentbläddrare -GenericName[ta]=ஆவண உலாவி -GenericName[tg]=Тафсири ҳуҷҷат -GenericName[th]=เครื่องมือเลือกดูแฟ้มเอกสาร -GenericName[tr]=Belge Tarayıcısı -GenericName[uk]=Навігатор документів -GenericName[uz]=Ҳужжат браузери -GenericName[ven]=Buronza ya manwalwa -GenericName[vi]=Trình duyệt tài liệu -GenericName[wa]=Foyteu di documints -GenericName[xh]=Umkhangeli Wencwadi Zoxwebhu -GenericName[xx]=xxDocument Browserxx -GenericName[zh_CN]=文档浏览器 -GenericName[zh_TW]=文件閱讀器 -GenericName[zu]=Umcingi Woshicilelo -X-KDE-StartupNotify=true -Icon=assistant-qt4 -Terminal=false -Type=Application - - -Name[bg]=Qt 4 асистент -Name[cs]=Qt4 asistent -Name[hu]=Qt 4 Asszisztens -Name[ja]=Qt 4アシスタント -Name[km]=អ្នក​ជំនួយការ Qt 4 -Name[nb]=Qt 4-assistent -Name[pa]=Qt 4 ਸਹਾਇਕ -Name[sv]=Qt 4-assistent -Name[zh_CN]=Qt 4 助手 -Name[zh_TW]=Qt 4 助理 diff --git a/share/samples/sample.4gl b/share/samples/sample.4gl deleted file mode 100644 index 894951d..0000000 --- a/share/samples/sample.4gl +++ /dev/null @@ -1,26 +0,0 @@ -FUNCTION ma_fonction3(ma_date) - DEFINE ma_date DATE - DEFINE mon_tableau ARRAY[20] OF RECORD - date_naiss DATE, - nom CHAR(20), - prenom CHAR(20), - ville CHAR(20) - END RECORD - DEFINE idx smallint - DECLARE c_date CURSOR FOR - SELECT date_naissance, nom, prenom, ville - FROM ma_table - LET idx=1 - FOREACH c_date INTO mon_tableau[idx].* # valoriser l'élément du tableau avec la rangée courante - LET idx = idx + 1 # incrémenter l'indice du tableau - END FOREACH - LET idx=idx-1 # le nombre exact d'éléments ( -1 car le foreach termine avec la valeur correcte + 1 ) - IF idx > 0 THEN - open window ma_window at 3,55 - with form "ma_forme" attribute (border) # créer une window en ligne 3, colonne 55, à partir de la forme ma_forme.per/frm - CALL set_count(idx) - DISPLAY ARRAY mon_tableau TO sa_tableau # afficher le contenu du tableau dans le screen record défini dans ma_forme.per - ELSE - ERROR "Pas de données à afficher" - END IF -END FUNCTION \ No newline at end of file diff --git a/share/samples/sample.abap b/share/samples/sample.abap deleted file mode 100644 index 7dd6af7..0000000 --- a/share/samples/sample.abap +++ /dev/null @@ -1,45 +0,0 @@ -* -* This program interprets the sequential file created by ZHEAVYPR -* and displays the "heavy" ABAPs of a specified period of time. -* The result is a list of ABAPS categorized by app. server and -* work process type, and sorted by a number: how many times -* that particular ABAP was found running for too long time (>5min) -* during that period. -* -REPORT ZHEAVYLS. - -DATA: INPUT_FILE(40) VALUE '/oracle/SID/sapreorg/heavy_abaps'. -PARAMETERS: DATE LIKE AMDS-ANDAT DEFAULT SY-DATUM, - FROMTIME LIKE PLKZ-AEUZEIT DEFAULT SY-UZEIT, - TOTIME LIKE PLKZ-AEUZEIT DEFAULT SY-UZEIT. - -DATA: BEGIN OF O, - 1(10), 2(8), 3(8), 4(3), 5(8), 6(8), -END OF O. -DATA: BEGIN OF A OCCURS 100, - 3(8), 4(3), 6(8), NUM TYPE I, -END OF A. - -OPEN DATASET INPUT_FILE FOR INPUT IN TEXT MODE. -DO. - READ DATASET INPUT_FILE INTO O. - IF SY-SUBRC <> 0.EXIT.ENDIF. - IF O-1 = DATE AND O-2 >= FROMTIME AND O-2 <= TOTIME. - MOVE-CORRESPONDING O TO A. A-NUM = 1. - COLLECT A. - ENDIF. -ENDDO. -CLOSE DATASET INPUT_FILE. - -WRITE: / DATE, FROMTIME, '---', TOTIME. -SKIP 2. -SORT A BY 3 4 NUM DESCENDING. -LOOP AT A. - AT NEW 3. - WRITE: / A-3 COLOR 2. - ENDAT. - AT NEW 4. - WRITE: / ' ',A-4 COLOR 3. - ENDAT. - WRITE: / ' ', A-6, A-NUM. -ENDLOOP. diff --git a/share/samples/sample.abc b/share/samples/sample.abc deleted file mode 100644 index 1ee1ae8..0000000 --- a/share/samples/sample.abc +++ /dev/null @@ -1,10 +0,0 @@ -X:1 -T:Note lengths and default note length -M:C -K:C -L:1/16 - A/2 A/ A A2 A3 A4 A6 A7 A8 A12 A15 A16|] -L:1/8 - A/4 A/2 A/ A A2 A3 A4 A6 A7 A8 A12 A15|] -L:1/4 -A/8 A/4 A/2 A/ A A2 A3 A4 A6 A7|] \ No newline at end of file diff --git a/share/samples/sample.adb b/share/samples/sample.adb deleted file mode 100644 index eae686e..0000000 --- a/share/samples/sample.adb +++ /dev/null @@ -1,53 +0,0 @@ --- User-defined types and subtypes. -with Gnat.Io; use Gnat.Io; -procedure Subr is - I : Integer; - - -- Creating a type equiv to integer. - subtype Also_Int is Integer; - Ai: Also_Int; - - -- Can limit the range of values. - Li: Integer range 1..10; - - -- Can also create a type which has limits. - subtype Degrees_Arc is Integer range 0..360; - Dist: Degrees_Arc; - - -- Can "clone" a new type. - type Temperature is new Integer; - type Width is new Integer; - T: Temperature; - W: Width; -begin - Ai := 2; - Put("How 'bout an integer? "); - Get(Li); - Li := Li + Ai; - Put("Sum is "); - Put(Li); - New_Line; - - Put_Line("How about temp and width?"); - Get(I); - T := Temperature(I); - Get(I); - W := Width(I); - T := T + Temperature(10); - W := Width(2)*W; - Put(Integer(T)); - Put(" "); - Put(Integer(W)); - New_Line; - - -- None of these will compile: - -- T := W; - -- Get(T); - -- W := 2*W; - - Put("The range of degrees is "); - Put(Degrees_Arc'First); - Put(" to "); - Put(Degrees_Arc'Last); - New_Line; -end Subr; diff --git a/share/samples/sample.as b/share/samples/sample.as deleted file mode 100644 index aba6c8d..0000000 --- a/share/samples/sample.as +++ /dev/null @@ -1,20 +0,0 @@ -private function getSlider1Num(e:Event):void { - var sNum:Number = xs1.passNum; - it1.text = String(sNum); -} - -private function getSlider2Num(e:Event):void { - var sNum2:Number = xs2.passNum; - it2.text = String(sNum2); -} - -private function scaleBox(e:Event):void { - var sNum3:Number = xs3.passNum; - redBox.scaleX = sNum3; - redBox.scaleY = sNum3; -} - -private function getSlider4Num(e:Event):void { - var sNum4:Number = xs4.passNum; - it3.text = String(sNum4); -} diff --git a/share/samples/sample.per b/share/samples/sample.per deleted file mode 100644 index 0efe36f..0000000 --- a/share/samples/sample.per +++ /dev/null @@ -1,45 +0,0 @@ -database ga4 -screen -{ - Saisie Des Interventions TLM - Comptes rendus journaliers - - Client : [f001 ][f002 ] Date [f003 ] - - Duree en Hres [f004 ] - Code Chantier [f005 ] - Intervenant [ab] [nom_inter ] - Nature Intervention [xx] [nom_nature ] - - Demande par [f006 ] - Libelle resume [f007 ] - Facturable ? [x] - - Detail Intervention - [f008 ] - [f009 ] - [f010 ] - [f011 ] - [f012 ] -} -end -tables -tlm,cttr -attributes -f001 = tlm.tier_no; -f002 = cttr.tier_nom, NOENTRY; -f003 = tlm.dat_pi; -f004 = tlm.duree, REQUIRED; -f005 = tlm.chantier, UPSHIFT; -ab = tlm.inter, UPSHIFT; -nom_inter = formonly.nom_inter type char ; -xx = tlm.nature ; -nom_nature = formonly.nom_nature type char ; -f006 = tlm.demande_par,UPSHIFT; -f007 = tlm.libelle,UPSHIFT; -x = tlm.flgfact,UPSHIFT,INCLUDE=("O","N"); -f008 = tlm.nat1,UPSHIFT; -f009 = tlm.nat2,UPSHIFT; -f010 = tlm.nat3,UPSHIFT; -f011 = tlm.nat4,UPSHIFT; -f012 = tlm.nat5,UPSHIFT; -end diff --git a/share/tests/bug213964.cpp b/share/tests/bug213964.cpp new file mode 100644 index 0000000..f2eaf57 --- /dev/null +++ b/share/tests/bug213964.cpp @@ -0,0 +1,139 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "bug213964.h" +#include "moc_bug213964.cpp" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +QTEST_KDEMAIN(BugTest, GUI) + +using namespace KTextEditor; + +static const char* text( +"# Instructions\n" +"# 1) Load this file. Do NOT edit anything.\n" +"# 2) Collapse the top level folding (Ctrl+Shift+-)\n" +"# 3) Type \"('\" on line 7 (without the double quotes, with the single quote) -> CRASH\n" +"# 4) Next time around, type the \"('\" on line 30 -> no crash\n" +"# 5) Delete the two chars again, and try step 3, now -> no crash\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"\n" +"xxx (x xx 2:xxxx(xx3)) {\n" +" xx3[,x] <- xx2[,x] + (xxx(xx2[,x-1])-xxx(xx2[,x-1]))/2 + xx3[1,x-1] - xx2[1,x-1]\n" +"}\n"); + +BugTest::BugTest() + : QObject() +{ +} + +BugTest::~BugTest() +{ +} + +void BugTest::reproduceCrash() +{ + KateGlobal::self()->incRef(); + KateDocument doc(false, false, false); + doc.setText(text); + doc.setHighlightingMode("R Script"); + doc.buffer().ensureHighlighted (75); + doc.foldingTree()->collapseToplevelNodes(); + doc.buffer().ensureHighlighted (75); + + doc.insertText(Cursor(6, 0), "("); + qDebug() << "!!! The next line usually crashes in the code folding code"; + QTest::qWait(500); + doc.insertText(Cursor(6, 1), "'"); + qDebug() << "!!! Huh, no crash. qWait above not long enough?"; +} diff --git a/share/tests/bug213964.h b/share/tests/bug213964.h new file mode 100644 index 0000000..07e564d --- /dev/null +++ b/share/tests/bug213964.h @@ -0,0 +1,38 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_BUG_213964_TEST_H +#define KATE_BUG_213964_TEST_H + +#include + +class BugTest : public QObject +{ + Q_OBJECT + +public: + BugTest(); + ~BugTest(); + +private Q_SLOTS: + void reproduceCrash(); + +}; + +#endif diff --git a/share/tests/bug242723_test.cpp b/share/tests/bug242723_test.cpp new file mode 100644 index 0000000..a7c72e5 --- /dev/null +++ b/share/tests/bug242723_test.cpp @@ -0,0 +1,70 @@ +/* This file is part of the KDE libraries + Copyright (C) 2011 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "bug242723_test.h" +#include "moc_bug242723_test.cpp" + +#include + +#include +#include +#include + +using namespace KTextEditor; + +QTEST_KDEMAIN(RemoveTrailingSpacesTest, GUI) + +RemoveTrailingSpacesTest::RemoveTrailingSpacesTest() + : QObject() +{ +} + +RemoveTrailingSpacesTest::~RemoveTrailingSpacesTest() +{ +} + +// remove trailing spaces should be blocked during the paste, +// as paste 1. removes text, 2. then remove-trailing-spaces +// moves content and then 3. insert text works on the modified +// content by 2. +void RemoveTrailingSpacesTest::testCopyPasteBug242723() +{ + KateDocument doc (false, false, false); + doc.config()->setRemoveTrailingDyn(true); + + // one edit action -> revision now 1, last saved still -1 + QString content("blah ( int a,\n" + " int b,\n" + " int c )\n"); + + doc.insertText(Cursor(0, 0), content); + + QCOMPARE(doc.text(), content); + + KateView* view = static_cast(doc.createView(0)); + + view->setSelection(Range(1, 7, 2, 12)); + + view->copy(); + view->paste(); + + QString after = doc.text(); + + QCOMPARE(doc.text(), content); +} diff --git a/share/tests/bug242723_test.h b/share/tests/bug242723_test.h new file mode 100644 index 0000000..eb5c2be --- /dev/null +++ b/share/tests/bug242723_test.h @@ -0,0 +1,37 @@ +/* This file is part of the KDE libraries + Copyright (C) 2011 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_REMOVE_TRAILING_SPACES_TEST_H +#define KATE_REMOVE_TRAILING_SPACES_TEST_H + +#include + +class RemoveTrailingSpacesTest : public QObject +{ + Q_OBJECT + +public: + RemoveTrailingSpacesTest(); + ~RemoveTrailingSpacesTest(); + +private Q_SLOTS: + void testCopyPasteBug242723(); +}; + +#endif // KATE_REMOVE_TRAILING_SPACES_TEST_H diff --git a/share/tests/bug286887.cpp b/share/tests/bug286887.cpp new file mode 100644 index 0000000..629ecbf --- /dev/null +++ b/share/tests/bug286887.cpp @@ -0,0 +1,93 @@ +/* This file is part of the KDE libraries + Copyright (C) 2012 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "bug286887.h" +#include "moc_bug286887.cpp" + +#include + +#include +#include +#include +#include + +QTEST_KDEMAIN(BugTest, GUI) + +using namespace KTextEditor; + +BugTest::BugTest() + : QObject() +{ +} + +BugTest::~BugTest() +{ +} + +void BugTest::initTestCase() +{ + KateGlobal::self()->incRef(); +} + +void BugTest::cleanupTestCase() +{ + KateGlobal::self()->decRef(); +} + +void BugTest::ctrlShiftLeft() +{ + KateDocument doc(false, false, false); + doc.config()->setWrapCursor(false); + + // view must be visible... + KateView* view = static_cast(doc.createView(0)); + view->show(); + view->resize(400, 300); + + // enable block mode, then set cursor after last character, then shift+left + doc.clear(); + view->setBlockSelection(true); + view->setCursorPosition(Cursor(0, 2)); + view->shiftCursorLeft(); + + QTest::qWait(500); + + // enable block mode, then set cursor after last character, then delete word left + doc.clear(); + view->setBlockSelection(true); + view->setCursorPosition(Cursor(0, 2)); + view->deleteWordLeft(); + + QTest::qWait(500); + + // disable wrap-cursor, then set cursor after last character, then shift+left + doc.clear(); + view->setBlockSelection(false); + doc.config()->setWrapCursor(true); + view->setCursorPosition(Cursor(0, 2)); + view->shiftCursorLeft(); + + QTest::qWait(500); + + // disable wrap-cursor, then set cursor after last character, then delete word left + doc.clear(); + view->setCursorPosition(Cursor(0, 2)); + view->deleteWordLeft(); +} + diff --git a/share/tests/bug286887.h b/share/tests/bug286887.h new file mode 100644 index 0000000..b6a7a35 --- /dev/null +++ b/share/tests/bug286887.h @@ -0,0 +1,40 @@ +/* This file is part of the KDE libraries + Copyright (C) 2012 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_BUG_286887_TEST_H +#define KATE_BUG_286887_TEST_H + +#include + +class BugTest : public QObject +{ + Q_OBJECT + +public: + BugTest(); + ~BugTest(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + void ctrlShiftLeft(); +}; + +#endif diff --git a/share/tests/bug294241.cpp b/share/tests/bug294241.cpp new file mode 100644 index 0000000..69fe780 --- /dev/null +++ b/share/tests/bug294241.cpp @@ -0,0 +1,167 @@ +/* This file is part of the KDE libraries + Copyright (C) 2012 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "bug294241.h" +#include "moc_bug294241.cpp" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +QTEST_KDEMAIN(BugTest, GUI) + +using namespace KTextEditor; + +BugTest::BugTest() + : QObject() +{ +} + +BugTest::~BugTest() +{ +} + +void BugTest::initTestCase() +{ + KateGlobal::self()->incRef(); +} + +void BugTest::cleanupTestCase() +{ + KateGlobal::self()->decRef(); +} + +void BugTest::tryXmlCrash() +{ + KateDocument doc(false, false, false); + QString url = KDESRCDIR + QString("bug294241.xml"); + doc.openUrl(url); + doc.discardDataRecovery(); + doc.setHighlightingMode("XML"); + doc.buffer().ensureHighlighted (doc.lines()); + + // view must be visible... + KateView* view = static_cast(doc.createView(0)); + view->show(); + view->resize(400, 300); + view->setCursorPosition(Cursor(502, 1)); + + doc.typeChars(view, " "); + doc.buffer().ensureHighlighted (doc.lines()); + qDebug() << "!!! The next line usually crashes in the code folding code"; + + QTest::qWait(2000); + doc.undo(); + doc.buffer().ensureHighlighted (doc.lines()); + + QTest::qWait(2000); + qDebug() << "!!! No crash (qWait not long enough)? Nice!"; +} + +void BugTest::tryPhpCrash() +{ + KateDocument doc(false, false, false); + QString url = KDESRCDIR + QString("bug294241.php"); + doc.openUrl(url); + doc.discardDataRecovery(); + doc.setHighlightingMode("PHP/PHP"); + doc.buffer().ensureHighlighted (doc.lines()); + + // view must be visible... + KateView* view = static_cast(doc.createView(0)); + view->show(); + view->resize(400, 300); + view->setCursorPosition(Cursor(22, 25)); + QTest::qWait(2000); + + qDebug() << "!!! The next line usually crashes in the code folding code"; + doc.typeChars(view, "h"); + doc.buffer().ensureHighlighted (doc.lines()); + QTest::qWait(1000); + doc.typeChars(view, "o"); + doc.buffer().ensureHighlighted (doc.lines()); + QTest::qWait(1000); + doc.typeChars(view, "?"); + doc.buffer().ensureHighlighted (doc.lines()); + QTest::qWait(1000); + doc.typeChars(view, ">"); + doc.buffer().ensureHighlighted (doc.lines()); + QTest::qWait(2000); + + qDebug() << "!!! No crash (qWait not long enough)? Nice!"; +} + +void BugTest::tryRubyCrash() +{ + int i = 0; + KateDocument doc(false, false, false); + QString url = KDESRCDIR + QString("bug294241.rb"); + doc.openUrl(url); + doc.discardDataRecovery(); + doc.setHighlightingMode("Ruby"); + doc.buffer().ensureHighlighted (doc.lines()); + + // view must be visible... + KateView* view = static_cast(doc.createView(0)); + view->show(); + view->resize(400, 300); + + // Select ruby code and uncomment it + view->setSelection(Range(6, 0, 26, 0)); + QTest::qWait(500); + view->toggleComment(); + QTest::qWait(500); + + // Now unindent + for (i = 0; i < 5; i++) + view->unIndent(); + QTest::qWait(2000); + + view->setCursorPosition(Cursor(5, 0)); + view->setSelection(Range()); + QTest::qWait(2000); + + for (i = 4; i >= 0; --i) { + view->setCursorPosition(Cursor(i, 0)); + view->keyDelete(); + } + view->keyDelete(); + QTest::qWait(1000); + + view->keyReturn(); + view->keyReturn(); + QTest::qWait(2000); + + qDebug() << "!!! The next line usually crashes in the code folding code"; + doc.undo(); + QTest::qWait(2000); + + qDebug() << "!!! No crash (qWait not long enough)? Nice!"; +} + + + + diff --git a/share/tests/bug294241.h b/share/tests/bug294241.h new file mode 100644 index 0000000..b9fca39 --- /dev/null +++ b/share/tests/bug294241.h @@ -0,0 +1,43 @@ +/* This file is part of the KDE libraries + Copyright (C) 2012 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_BUG_294241_TEST_H +#define KATE_BUG_294241_TEST_H + +#include + +class BugTest : public QObject +{ + Q_OBJECT + +public: + BugTest(); + ~BugTest(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + void tryXmlCrash(); + void tryPhpCrash(); + void tryRubyCrash(); + +}; + +#endif diff --git a/share/tests/bug294241.php b/share/tests/bug294241.php new file mode 100644 index 0000000..420d518 --- /dev/null +++ b/share/tests/bug294241.php @@ -0,0 +1,44 @@ +get('type', 0); +$style1 = $params->get('style1', ''); +$style2 = $params->get('style2', ''); +$html = $params->get('html', ''); +$relativeedge = (int) $params->get('relativeedge', 0); // 0 - top +$id = 'floating_box_'.$module->id; + +echo '
'.$html.'
'; +?> + + \ No newline at end of file diff --git a/share/tests/bug294241.rb b/share/tests/bug294241.rb new file mode 100644 index 0000000..495a75d --- /dev/null +++ b/share/tests/bug294241.rb @@ -0,0 +1,26 @@ + + + + + + +# if a +# return a +# elsif $10 +# return Token.new(T_LBRA, $+) +# elsif $11 +# return Token.new(T_RBRA, $+) +# elsif $12 +# len = $+.to_i +# val = @str[@pos, len] +# @pos += len +# return Token.new(T_LITERAL, val) +# elsif $13 +# return Token.new(T_PLUS, $+) +# elsif $14 +# return Token.new(T_PERCENT, $+) +# elsif $15 +# return Token.new(T_CRLF, $+) +# elsif $16 +# return Token.new(T_EOF, $+) +# end diff --git a/share/tests/bug294241.xml b/share/tests/bug294241.xml new file mode 100644 index 0000000..0048fa7 --- /dev/null +++ b/share/tests/bug294241.xml @@ -0,0 +1,565 @@ + + + +]> +
+Printer Configuration + + +&TC.Hollingsworth; + + + +2012-02-16 +&kde; 4.8 + + +KDE +Systemsettings +printer +CUPS + + + + +Adding a New Printer + +To add a new printer, select the New Printer node +from the left pane. There you will find two options: + + +New Printer + +To add a new printer which is connected to your local computer, home +network or on the Internet, select the New Network Printer +button. A new window will open where you can specify your printer +configuration. + + + +Choose the type of connection your printer uses from the left pane, then +input the required details for the connection type in the right pane, and then +click the Forward to proceed. + + + +On the next page, you may select the manufacturer of your printer from +the list provided, or select a Postscript Printer Description +(PPD) file. Then, click the Forward +button. + +On the next page, you can select the model of printer from the left, and +select the driver to use on the right. If you aren't sure which driver to use, +choose the driver that ends with (reccomended), which will +be selected by default. + + + +Finally, enter a name for your printer in the +Printer Name field if you wish to change the default. You +may also enter the Description and +Location if you would like, but these fields are optional. + + +Click the OK to configure the printer. + + + + +New Printer Class + +To add a new printer class that specifies a group of printers to print to, +click on the New Printer Class button. + +On the first page, you must enter a name for the class in the +Printer Name field. You may also optionally enter the +Location. Then, click Next. + +On the next page, you will see a list of printers present in the class on +the left, and all other printers configured on your system on the right. To +add a printer to the class, select it from the right and click the +Left Arrow button. To remove a printer from the class, +select it from the left and click the Right Arrow button. + + +Finally, click OK to create the new printer class. + + + + + + +Configuring a Printer + +All printers configured on your system will be listed under the Local +Printers node. Select a printer from the list, and configuration options for it +will appear on the right. + +Printer options are sorted into four groups, which can be accessed using +the tabs on the top. + + +Settings + +The Settings tab allows you to view basic +configuration information about your printer like the driver it uses, as well +as perform basic actions like printing a test page. + +The following options are available: + + + + +Printer Description + + + + +Location +An optional description of the printer's location. + + + +Printer Description +A textual description of the printer, that will be displayed +alongside it in many applications. + + + +Device URI +The Uniform Resource Idenitfier of your printer. This may be +a &URL; for a printer on the Internet, a &Unix; device file, or another URI +used by CUPS to locate your pritner. + + + +This is the default printer +This allows you to select this printer as the default printer. +The default printer will be automatically selected when invoking the Print +option of applications. +If this is the only configured printer, this option will be disabled. + + + + + + + + +Printer Description + + + + +Printer Model +This describes the manufacturer and model of the printer, and +also lists the driver currently in use. + + + + +Change +Select this button to change the manufacturer, model, or driver +of this printer. + + + +Printer State +This describes the current state of your printer. If it's not +printing, it will say Idle, otherwise it might inform you +that your printer is currently printing, or that there is an error, like a printer +jam or that it is of paper or ink. + + + + + + + +Printer Status + + + + + +Printer Status + + + + +Enable +When this checkbox is selected, the printer will print any jobs +that it currently has or accepts. When disabled, it will not print. + + + +Accepting +When this checkbox is selected, the printer will accept new jobs. +When disabled, it will not accept new jobs. + + +If you plan to take a printer offline for a short time, but want it to +continue to accept jobs that will be printed when it is restored, you can +unselect Enabled but leave Accepting +enabled. If you plan to take a printer offline for a long time, you could +leave Enabled selected but uncheck Accepting, +so the printer will print all remaining jobs but not accept any new ones. + + + + + + +Sharing +This enables or disabled sharing the printer with other computers. + + + + +Print Test Page +Click this button to print a test page using this printer, to +verify that it is working correctly. + + + + + + + + + + +Policies + +The Policies tab allows you to add a banner to every +page printer and disable or enable it for certain users. + + +Banner Settings + + +A banner page is a special page that is printer before or after a printed +document, and may optionally define a header or footer that is displayed on a +document. For more information on banners, see +the relevant section +of the CUPS documentation. + + + + +Starting Banner +Select a banner page that is printed before +every printed document. + + + +Ending Banner +Select a banner page that is printed after +every printed document. + + + + + + + +User and Group Permissions + + +This permits you to enable or disable this printer for certain users or +groups on your system. + + +To configure it such that only the listed users or groups can user the +printer, select Deny printing for everyone except these users. +To configure it such that all users and groups can print except +those listed, select Allow printing for everyone except these users. + + +To add a user or group to the list, click the Add +button, then enter the username or group name. To remove a user or group from +the list, select it and click the Remove button. + + + + + + + +Printer Options + +The Printer Options tab allows you to select options +that will be applied by default to various jobs, like the size or type of the +paper used or the quality of printing that the printer will perform. + + + + +Media Size +This lets you select the size of the media being printed on. A +list of standard sizes is provided. + + + +Double-Sided Printing +This enables or disabled double-sided printing, which may or +may not be automatic depending on the model of printer used. + + + +Media Source +This allows you to select for instance the tray that will be +used, if your printer has multiple paper trays. + + + +Output Mode +This permits you to configure the printer to configure in color +or grayscale, if your printer supports doing so. + + + +Media Type +This permits you to select the type of media that will be printed +on. This usually is as simple as plain or photo paper, but advanced printers can +directly print on things like CD or DVD discs. + + + +Print Quality +This lets you choose the quality of printed documents. Higher +quality printed documents generally appear better than lower quality ones, but +they will also take longer to print and use more ink or toner. + + + +Duplexer Installed +Printers that support a duplexer can print to both sides of a +page automatically, usually by mechanically flipping the page. Select this option +if your printer supports this. + + + + + + +Job Options + +The Job Options tab lets you select the default +settings that are applied to each print job, like the number of copies to be +printed. These options can be changed in the print dialog of all &kde; applications +as well as many others. + +Each option listed below, except for the custom options, provides a +Reset to the right of the option. Click this button to +restore that setting to its default value. + + + + +Common Options + + + +Copies +Each documented printed will be printed the number of times +configured here. + + + +Orientation +Allows you to select the orientation of printed documents, such +as Portriat or Landscape. + + + +Scale to fit +When this option is selected, documents larger than the media +will be shrunk to fit completely on it, while smaller documents will be expanded. + + + + +Pages per side +This lets you print multiple pages on one page, for instance +by splitting it in half. + + + +Pages per side layout +This lets you select how multiple pages printed on one page will +be arranged. + + + +Brightness +This configures the darkness of the printed document. + + + +Finishings +Some printers support optional finishings, such as staples, hole +punches, or folding. If you printer supports this, you may select one here. + + + + +Job priority +Some print servers will print certain jobs before others. This +allows you to ensure your job is printed quickly or after more important ones. + + + + +Media +This configures the size of media that the job will be printed +on. + + + +Sides +This configures double-sided printing. + + + +Hold until +This instructs the print server to not print your job until +a specified time, or never. + + + + + + + +Image Options + + +These options affect only printed images. + + + + +Mirror +If selected, the image will be reversed, as if it appeared in a +mirror. + + + +Scaling +This permits you to reduce or enlarge the image to a specified +size. + + + +Saturation +This configures the saturation, or intensity, or the color +printed. For more information, see +the Saturation +article on Wikipedia. + + + +Hue adjustment +This shifts the hue, or pure color, of the image. For more +information, see the Hue article +on Wikipedia. + + + +Gamma +This affects the gamma correction of the image. For more information, see +the Gamma Correction +article on Wikipedia. + + + + + + + +Text Options + +These options affect only jobs that consist solely of plain text. + + + +Characters per inch +Configures the density of characters in the printed document. + + + + +Lines per inch +Configures the density of lines in the printed document. + + + + +You can configure the size of the left, right, top, and bottom +margins in the number selection boxes provided. + + + +The Settings tab allows you to view Printer Description, Driver Details, and printer Status. + +The Policies tab allows you to edit Banner Settings, and User and Group Permissions. + +In the Options tab, you can set printout details like size, source, and mode. + +In the Job Options tab, you can specify the default job options for your printer like, common options, image options, and text options. + +The following is an example of how your window might look after configuration. + +[Image5.png] [Image6.png] [Image7.png] [Image9.png] + + +EDITING SERVER SETTINGS + +You will find this node as 'Server Settings' on the left pane where you can configure the basic server settings of your printer. + +The window has 5 options. + +Check the first box if you want to view printers shared by other systems. + +Check the second box to share published printers connected to your system. Subsequently a sub-node will be activated which allows you to activate printing from the Internet. + +Selectthe third box to allow remote administration of your printers. + +Select the forth box to allow users to cancel any job, which is not just their own. + +Selectthe fifth box to save debugging information for troubleshooting. + +Below is a image of the server configuration window. + +[Image8.png] + +LOCAL PRINTERS + +The local printers option on the left pane has a list of your installed printers as described earlier. + +There is also an option Print_to_PDF under this section. +Note: Print_to_PDF section did not work on my version of KDE. + + + + +
+ + diff --git a/share/tests/bug294750.cpp b/share/tests/bug294750.cpp new file mode 100644 index 0000000..e50c436 --- /dev/null +++ b/share/tests/bug294750.cpp @@ -0,0 +1,89 @@ +/* This file is part of the KDE libraries + Copyright (C) 2012 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "bug294750.h" +#include "moc_bug294750.cpp" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +QTEST_KDEMAIN(BugTest, GUI) + +using namespace KTextEditor; + +BugTest::BugTest() + : QObject() +{ +} + +BugTest::~BugTest() +{ +} + +void BugTest::initTestCase() +{ + KateGlobal::self()->incRef(); +} + +void BugTest::cleanupTestCase() +{ + KateGlobal::self()->decRef(); +} + +void BugTest::tryCrash() +{ + KateDocument doc(false, false, false); + QString url = KDESRCDIR + QString("folding-crash.py"); + doc.openUrl(url); + doc.discardDataRecovery(); + doc.setHighlightingMode("Python"); + doc.buffer().ensureHighlighted (doc.lines()); + + // view must be visible... + KateView* view = static_cast(doc.createView(0)); + view->show(); + view->resize(400, 300); + + // fold all + doc.foldingTree()->collapseToplevelNodes(); + QTest::qWait(1000); + + view->down(); + view->down(); + view->end(); + view->cursorRight(); + view->down(); + view->down(); + view->end(); + QTest::qWait(1000); + + qDebug() << "!!! The next line usually crashes in the code folding code"; + view->backspace(); + + doc.buffer().ensureHighlighted (doc.lines()); + QTest::qWait(1000); +} diff --git a/share/tests/bug294750.h b/share/tests/bug294750.h new file mode 100644 index 0000000..80a17e7 --- /dev/null +++ b/share/tests/bug294750.h @@ -0,0 +1,41 @@ +/* This file is part of the KDE libraries + Copyright (C) 2012 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_BUG_294750_TEST_H +#define KATE_BUG_294750_TEST_H + +#include + +class BugTest : public QObject +{ + Q_OBJECT + +public: + BugTest(); + ~BugTest(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + void tryCrash(); + +}; + +#endif diff --git a/share/tests/bug294756.cpp b/share/tests/bug294756.cpp new file mode 100644 index 0000000..d5ad51e --- /dev/null +++ b/share/tests/bug294756.cpp @@ -0,0 +1,86 @@ +/* This file is part of the KDE libraries + Copyright (C) 2012 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "bug294756.h" +#include "moc_bug294756.cpp" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +QTEST_KDEMAIN(BugTest, GUI) + +using namespace KTextEditor; + +BugTest::BugTest() + : QObject() +{ +} + +BugTest::~BugTest() +{ +} + +void BugTest::initTestCase() +{ + KateGlobal::self()->incRef(); +} + +void BugTest::cleanupTestCase() +{ + KateGlobal::self()->decRef(); +} + +void BugTest::tryCrash() +{ + KateDocument doc(false, false, false); + QString url = KDESRCDIR + QString("folding-crash.py"); + doc.openUrl(url); + doc.discardDataRecovery(); + doc.setHighlightingMode("Python"); + doc.buffer().ensureHighlighted (doc.lines()); + + // view must be visible... + KateView* view = static_cast(doc.createView(0)); + view->show(); + view->resize(400, 300); + + // fold all + doc.foldingTree()->collapseToplevelNodes(); + QTest::qWait(1000); + + view->down(); + view->down(); + view->down(); + view->cursorLeft(); + QTest::qWait(1000); + + qDebug() << "!!! The next line usually crashes in the code folding code"; + view->backspace(); + + doc.buffer().ensureHighlighted (doc.lines()); + QTest::qWait(1000); +} diff --git a/share/tests/bug294756.h b/share/tests/bug294756.h new file mode 100644 index 0000000..aa85314 --- /dev/null +++ b/share/tests/bug294756.h @@ -0,0 +1,41 @@ +/* This file is part of the KDE libraries + Copyright (C) 2012 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_BUG_294756_TEST_H +#define KATE_BUG_294756_TEST_H + +#include + +class BugTest : public QObject +{ + Q_OBJECT + +public: + BugTest(); + ~BugTest(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + void tryCrash(); + +}; + +#endif diff --git a/share/tests/codecompletiontestmodel.cpp b/share/tests/codecompletiontestmodel.cpp new file mode 100644 index 0000000..059074e --- /dev/null +++ b/share/tests/codecompletiontestmodel.cpp @@ -0,0 +1,179 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Hamish Rodda + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "codecompletiontestmodel.h" + +#include +#include +#include +#include +#include +#include + +CodeCompletionTestModel::CodeCompletionTestModel(KTextEditor::View* parent, const QString &startText) + : KTextEditor::CodeCompletionModel(parent), m_startText(startText), m_autoStartText(m_startText.isEmpty()) +{ + setRowCount(40); + + Q_ASSERT(cc()); + + cc()->setAutomaticInvocationEnabled(true); + cc()->unregisterCompletionModel(KateGlobal::self()->wordCompletionModel()); //would add additional items, we don't want that in tests + cc()->registerCompletionModel(this); +} + +// Fake a series of completions +QVariant CodeCompletionTestModel::data( const QModelIndex & index, int role ) const +{ + switch (role) { + case Qt::DisplayRole: + if (index.row() < rowCount() / 2) + switch (index.column()) { + case Prefix: + switch (index.row() % 3) { + default: + return "void "; + case 1: + return "const QString& "; + case 2: + if (index.row() % 6) + return "inline virtual bool "; + return "virtual bool "; + } + + case Scope: + switch (index.row() % 4) { + default: + return QString(); + case 1: + return "KTextEditor::"; + case 2: + return "::"; + case 3: + return "std::"; + } + + case Name: + return QString(m_startText + QString("%1%2%3").arg(QChar('a' + (index.row() % 3))).arg(QChar('a' + index.row())).arg(index.row())); + + case Arguments: + switch (index.row() % 5) { + default: + return "()"; + case 1: + return "(bool trigger)"; + case 4: + return "(const QString& name, Qt::CaseSensitivity cs)"; + case 5: + return "(int count)"; + } + + case Postfix: + switch (index.row() % 3) { + default: + return " const"; + case 1: + return " KDE_DEPRECATED"; + case 2: + return ""; + } + } + else + switch (index.column()) { + case Prefix: + switch (index.row() % 3) { + default: + return "void "; + case 1: + return "const QString "; + case 2: + return "bool "; + } + + case Scope: + switch (index.row() % 4) { + default: + return QString(); + case 1: + return "KTextEditor::"; + case 2: + return "::"; + case 3: + return "std::"; + } + + case Name: + return QString(m_startText + QString("%1%2%3").arg(QChar('a' + (index.row() % 3))).arg(QChar('a' + index.row())).arg(index.row())); + + default: + return ""; + } + break; + + case Qt::DecorationRole: + break; + + case CompletionRole: { + CompletionProperties p; + if (index.row() < rowCount() / 2) + p |= Function; + else + p |= Variable; + switch (index.row() % 3) { + case 0: + p |= Const | Public; + break; + case 1: + p |= Protected; + break; + case 2: + p |= Private; + break; + } + return (int)p; + } + + case ScopeIndex: + return (index.row() % 4 ) - 1; + } + + return QVariant(); +} + +KTextEditor::View* CodeCompletionTestModel::view( ) const +{ + return static_cast(const_cast(QObject::parent())); +} + +KTextEditor::CodeCompletionInterface * CodeCompletionTestModel::cc( ) const +{ + return dynamic_cast(const_cast(QObject::parent())); +} + +void CodeCompletionTestModel::completionInvoked(KTextEditor::View* view, const KTextEditor::Range& range, InvocationType invocationType) +{ + Q_UNUSED(invocationType) + + if (m_autoStartText) { + m_startText = view->document()->text(KTextEditor::Range(range.start(), view->cursorPosition())); + } + kDebug() << m_startText; +} + + +#include "codecompletiontestmodel.moc" diff --git a/share/tests/codecompletiontestmodel.h b/share/tests/codecompletiontestmodel.h new file mode 100644 index 0000000..c33a200 --- /dev/null +++ b/share/tests/codecompletiontestmodel.h @@ -0,0 +1,47 @@ +/* This file is part of the KDE project + Copyright (C) 2005 Hamish Rodda + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef CODECOMPLETIONTEST_H +#define CODECOMPLETIONTEST_H + +#include + +namespace KTextEditor { + class View; + class CodeCompletionInterface; +} + +class CodeCompletionTestModel : public KTextEditor::CodeCompletionModel +{ + Q_OBJECT + + public: + CodeCompletionTestModel(KTextEditor::View* parent = 0L, const QString &startText = QString()); + + KTextEditor::View* view() const; + KTextEditor::CodeCompletionInterface* cc() const; + + virtual void completionInvoked(KTextEditor::View* view, const KTextEditor::Range& range, InvocationType invocationType); + virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const; + + private: + QString m_startText; + bool m_autoStartText; +}; + +#endif diff --git a/share/tests/codecompletiontestmodels.h b/share/tests/codecompletiontestmodels.h new file mode 100644 index 0000000..138a66d --- /dev/null +++ b/share/tests/codecompletiontestmodels.h @@ -0,0 +1,166 @@ +/* This file is part of the KDE libraries + Copyright (C) 2008 Niko Sams + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_COMPLETIONTESTMODELS_H +#define KATE_COMPLETIONTESTMODELS_H + +#include "codecompletiontestmodel.h" +#include + +#include +#include + +using namespace KTextEditor; + + +class CustomRangeModel : public CodeCompletionTestModel, public CodeCompletionModelControllerInterface3 +{ + Q_OBJECT + Q_INTERFACES(KTextEditor::CodeCompletionModelControllerInterface3) +public: + CustomRangeModel(KTextEditor::View* parent = 0L, const QString &startText = QString()) + : CodeCompletionTestModel(parent, startText) + {} + Range completionRange(View* view, const Cursor &position) + { + Range range = CodeCompletionModelControllerInterface3::completionRange(view, position); + if (range.start().column() > 0) { + KTextEditor::Range preRange(Cursor(range.start().line(), range.start().column()-1), + Cursor(range.start().line(), range.start().column())); + kDebug() << preRange << view->document()->text(preRange); + if (view->document()->text(preRange) == "$") { + range.expandToRange(preRange); + kDebug() << "using custom completion range" << range; + } + } + return range; + } + + bool shouldAbortCompletion(View* view, const Range& range, const QString ¤tCompletion) + { + Q_UNUSED(view); + Q_UNUSED(range); + static const QRegExp allowedText("^\\$?(\\w*)"); + return !allowedText.exactMatch(currentCompletion); + } +}; + +class CustomAbortModel : public CodeCompletionTestModel, public CodeCompletionModelControllerInterface3 +{ + Q_OBJECT + Q_INTERFACES(KTextEditor::CodeCompletionModelControllerInterface3) +public: + CustomAbortModel(KTextEditor::View* parent = 0L, const QString &startText = QString()) + : CodeCompletionTestModel(parent, startText) + {} + + bool shouldAbortCompletion(View* view, const Range& range, const QString ¤tCompletion) + { + Q_UNUSED(view); + Q_UNUSED(range); + static const QRegExp allowedText("^([\\w-]*)"); + return !allowedText.exactMatch(currentCompletion); + } +}; + +class EmptyFilterStringModel : public CodeCompletionTestModel, public CodeCompletionModelControllerInterface3 +{ + Q_OBJECT + Q_INTERFACES(KTextEditor::CodeCompletionModelControllerInterface3) +public: + EmptyFilterStringModel(KTextEditor::View* parent = 0L, const QString &startText = QString()) + : CodeCompletionTestModel(parent, startText) + {} + + QString filterString(View*, const Range&, const Cursor &) + { + return QString(); + } +}; + +class UpdateCompletionRangeModel : public CodeCompletionTestModel, public CodeCompletionModelControllerInterface3 +{ + Q_OBJECT + Q_INTERFACES(KTextEditor::CodeCompletionModelControllerInterface3) +public: + UpdateCompletionRangeModel(KTextEditor::View* parent = 0L, const QString &startText = QString()) + : CodeCompletionTestModel(parent, startText) + {} + + Range updateCompletionRange(View* view, const Range& range) + { + Q_UNUSED(view); + if (view->document()->text(range) == QString("ab")) { + return Range(Cursor(range.start().line(), 0), range.end()); + } + return range; + } + bool shouldAbortCompletion(View* view, const Range &range, const QString ¤tCompletion) + { + Q_UNUSED(view); + Q_UNUSED(range); + Q_UNUSED(currentCompletion); + return false; + } +}; + +class StartCompletionModel : public CodeCompletionTestModel, public CodeCompletionModelControllerInterface3 +{ + Q_OBJECT + Q_INTERFACES(KTextEditor::CodeCompletionModelControllerInterface3) +public: + StartCompletionModel(KTextEditor::View* parent = 0L, const QString &startText = QString()) + : CodeCompletionTestModel(parent, startText) + {} + + bool shouldStartCompletion(View* view, const QString &insertedText, bool userInsertion, const Cursor &position) + { + Q_UNUSED(view); + Q_UNUSED(userInsertion); + Q_UNUSED(position); + if(insertedText.isEmpty()) + return false; + + QChar lastChar = insertedText.at(insertedText.count() - 1); + if (lastChar == '%') { + return true; + } + return false; + } +}; + +class ImmideatelyAbortCompletionModel : public CodeCompletionTestModel, public CodeCompletionModelControllerInterface3 +{ + Q_OBJECT + Q_INTERFACES(KTextEditor::CodeCompletionModelControllerInterface3) +public: + ImmideatelyAbortCompletionModel(KTextEditor::View* parent = 0L, const QString &startText = QString()) + : CodeCompletionTestModel(parent, startText) + {} + + virtual bool shouldAbortCompletion(KTextEditor::View* view, const KTextEditor::Range& range, const QString& currentCompletion) + { + Q_UNUSED(view); + Q_UNUSED(range); + Q_UNUSED(currentCompletion); + return true; + } +}; + +#endif diff --git a/share/tests/completion_test.cpp b/share/tests/completion_test.cpp new file mode 100644 index 0000000..f4f8c08 --- /dev/null +++ b/share/tests/completion_test.cpp @@ -0,0 +1,342 @@ +/* This file is part of the KDE libraries + Copyright (C) 2008 Niko Sams + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "completion_test.h" + +#include "codecompletiontestmodels.h" +#include "codecompletiontestmodels.moc" + +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +QTEST_KDEMAIN(CompletionTest, GUI) + + +using namespace KTextEditor; + +int countItems(KateCompletionModel *model) +{ + int ret = 0; + for (int i=0; i < model->rowCount(QModelIndex()); ++i) { + ret += model->rowCount(model->index(i, 0)); + } + return ret; +} + +static void invokeCompletionBox(KateView* view) +{ + QTest::qWait(1000); // needed, otherwise, test fails + view->userInvokedCompletion(); + QTest::qWait(1000); // wait until code completion pops up + QVERIFY(view->completionWidget()->isCompletionActive()); +} + + +void CompletionTest::init() +{ + if ( !KSycoca::isAvailable() ) + QSKIP( "ksycoca not available", SkipAll ); + + Editor* editor = EditorChooser::editor(); + QVERIFY(editor); + + m_doc = editor->createDocument(this); + QVERIFY(m_doc); + m_doc->setText("aa bb cc\ndd"); + + KTextEditor::View *v = m_doc->createView(0); + QApplication::setActiveWindow(v); + m_view = static_cast(v); + Q_ASSERT(m_view); + + //view needs to be shown as completion won't work if the cursor is off screen + m_view->show(); +} + +void CompletionTest::cleanup() +{ + delete m_view; + delete m_doc; +} + +void CompletionTest::testFilterEmptyRange() +{ + KateCompletionModel *model = m_view->completionWidget()->model(); + + new CodeCompletionTestModel(m_view, "a"); + m_view->setCursorPosition(Cursor(0, 0)); + invokeCompletionBox(m_view); + + QCOMPARE(countItems(model), 40); + m_view->insertText("aa"); + QTest::qWait(1000); // process events + QCOMPARE(countItems(model), 14); +} + +void CompletionTest::testFilterWithRange() +{ + KateCompletionModel *model = m_view->completionWidget()->model(); + + CodeCompletionTestModel* testModel = new CodeCompletionTestModel(m_view, "a"); + m_view->setCursorPosition(Cursor(0, 2)); + invokeCompletionBox(m_view); + + Range complRange = *m_view->completionWidget()->completionRange(testModel); + QCOMPARE(complRange, Range(Cursor(0, 0), Cursor(0, 2))); + QCOMPARE(countItems(model), 14); + + m_view->insertText("a"); + QTest::qWait(1000); // process events + QCOMPARE(countItems(model), 1); +} + + +void CompletionTest::testAbortCursorMovedOutOfRange() +{ + KateCompletionModel *model = m_view->completionWidget()->model(); + + new CodeCompletionTestModel(m_view, "a"); + m_view->setCursorPosition(Cursor(0, 2)); + invokeCompletionBox(m_view); + + QCOMPARE(countItems(model), 14); + QVERIFY(m_view->completionWidget()->isCompletionActive()); + + m_view->setCursorPosition(Cursor(0, 4)); + QTest::qWait(1000); // process events + QVERIFY(!m_view->completionWidget()->isCompletionActive()); +} + +void CompletionTest::testAbortInvalidText() +{ + KateCompletionModel *model = m_view->completionWidget()->model(); + + new CodeCompletionTestModel(m_view, "a"); + m_view->setCursorPosition(Cursor(0, 2)); + invokeCompletionBox(m_view); + + QCOMPARE(countItems(model), 14); + QVERIFY(m_view->completionWidget()->isCompletionActive()); + + m_view->insertText("."); + QTest::qWait(1000); // process events + QVERIFY(!m_view->completionWidget()->isCompletionActive()); +} + +void CompletionTest::testCustomRange1() +{ + m_doc->setText("$aa bb cc\ndd"); + KateCompletionModel *model = m_view->completionWidget()->model(); + + CodeCompletionTestModel* testModel = new CustomRangeModel(m_view, "$a"); + m_view->setCursorPosition(Cursor(0, 3)); + invokeCompletionBox(m_view); + + Range complRange = *m_view->completionWidget()->completionRange(testModel); + kDebug() << complRange; + QCOMPARE(complRange, Range(Cursor(0, 0), Cursor(0, 3))); + QCOMPARE(countItems(model), 14); + + m_view->insertText("a"); + QTest::qWait(1000); // process events + QCOMPARE(countItems(model), 1); +} + +void CompletionTest::testCustomRange2() +{ + m_doc->setText("$ bb cc\ndd"); + KateCompletionModel *model = m_view->completionWidget()->model(); + + CodeCompletionTestModel* testModel = new CustomRangeModel(m_view, "$a"); + m_view->setCursorPosition(Cursor(0, 1)); + invokeCompletionBox(m_view); + + Range complRange = *m_view->completionWidget()->completionRange(testModel); + QCOMPARE(complRange, Range(Cursor(0, 0), Cursor(0, 1))); + QCOMPARE(countItems(model), 40); + + m_view->insertText("aa"); + QTest::qWait(1000); // process events + QCOMPARE(countItems(model), 14); +} + +void CompletionTest::testCustomRangeMultipleModels() +{ + m_doc->setText("$a bb cc\ndd"); + KateCompletionModel *model = m_view->completionWidget()->model(); + + CodeCompletionTestModel* testModel1 = new CustomRangeModel(m_view, "$a"); + CodeCompletionTestModel* testModel2 = new CodeCompletionTestModel(m_view, "a"); + m_view->setCursorPosition(Cursor(0, 1)); + invokeCompletionBox(m_view); + + QCOMPARE(Range(*m_view->completionWidget()->completionRange(testModel1)), Range(Cursor(0, 0), Cursor(0, 2))); + QCOMPARE(Range(*m_view->completionWidget()->completionRange(testModel2)), Range(Cursor(0, 1), Cursor(0, 2))); + QCOMPARE(model->currentCompletion(testModel1), QString("$")); + QCOMPARE(model->currentCompletion(testModel2), QString("")); + QCOMPARE(countItems(model), 80); + + + m_view->insertText("aa"); + QTest::qWait(1000); // process events + QCOMPARE(model->currentCompletion(testModel1), QString("$aa")); + QCOMPARE(model->currentCompletion(testModel2), QString("aa")); + QCOMPARE(countItems(model), 14*2); +} + +void CompletionTest::testAbortController() +{ + KateCompletionModel *model = m_view->completionWidget()->model(); + + new CustomRangeModel(m_view, "$a"); + m_view->setCursorPosition(Cursor(0, 0)); + invokeCompletionBox(m_view); + + QCOMPARE(countItems(model), 40); + QVERIFY(m_view->completionWidget()->isCompletionActive()); + + m_view->insertText("$a"); + QTest::qWait(1000); // process events + QVERIFY(m_view->completionWidget()->isCompletionActive()); + + m_view->insertText("."); + QTest::qWait(1000); // process events + QVERIFY(!m_view->completionWidget()->isCompletionActive()); +} + +void CompletionTest::testAbortControllerMultipleModels() +{ + KateCompletionModel *model = m_view->completionWidget()->model(); + + CodeCompletionTestModel* testModel1 = new CodeCompletionTestModel(m_view, "aa"); + CodeCompletionTestModel* testModel2 = new CustomAbortModel(m_view, "a-"); + m_view->setCursorPosition(Cursor(0, 0)); + invokeCompletionBox(m_view); + + QCOMPARE(countItems(model), 80); + QVERIFY(m_view->completionWidget()->isCompletionActive()); + + m_view->insertText("a"); + QTest::qWait(1000); // process events + QVERIFY(m_view->completionWidget()->isCompletionActive()); + QCOMPARE(countItems(model), 80); + + m_view->insertText("-"); + QTest::qWait(1000); // process events + QVERIFY(m_view->completionWidget()->isCompletionActive()); + QVERIFY(!m_view->completionWidget()->completionRanges().contains(testModel1)); + QVERIFY(m_view->completionWidget()->completionRanges().contains(testModel2)); + + QCOMPARE(countItems(model), 40); + + m_view->insertText(" "); + QTest::qWait(1000); // process events + QVERIFY(!m_view->completionWidget()->isCompletionActive()); +} + +void CompletionTest::testEmptyFilterString() +{ + KateCompletionModel *model = m_view->completionWidget()->model(); + + new EmptyFilterStringModel(m_view, "aa"); + m_view->setCursorPosition(Cursor(0, 0)); + invokeCompletionBox(m_view); + + QCOMPARE(countItems(model), 40); + + m_view->insertText("a"); + QTest::qWait(1000); // process events + QCOMPARE(countItems(model), 40); + + m_view->insertText("bam"); + QTest::qWait(1000); // process events + QCOMPARE(countItems(model), 40); +} + +void CompletionTest::testUpdateCompletionRange() +{ + m_doc->setText("ab bb cc\ndd"); + KateCompletionModel *model = m_view->completionWidget()->model(); + + CodeCompletionTestModel* testModel = new UpdateCompletionRangeModel(m_view, "ab ab"); + m_view->setCursorPosition(Cursor(0, 3)); + invokeCompletionBox(m_view); + + QCOMPARE(countItems(model), 40); + QCOMPARE(Range(*m_view->completionWidget()->completionRange(testModel)), Range(Cursor(0, 3), Cursor(0, 3))); + + m_view->insertText("ab"); + QTest::qWait(1000); // process events + QCOMPARE(Range(*m_view->completionWidget()->completionRange(testModel)), Range(Cursor(0, 0), Cursor(0, 5))); + QCOMPARE(countItems(model), 40); +} + +void CompletionTest::testCustomStartCompl() +{ + KateCompletionModel *model = m_view->completionWidget()->model(); + + m_view->completionWidget()->setAutomaticInvocationDelay(1); + + new StartCompletionModel(m_view, "aa"); + + m_view->setCursorPosition(Cursor(0, 0)); + m_view->insertText("%"); + QTest::qWait(1000); + + QVERIFY(m_view->completionWidget()->isCompletionActive()); + QCOMPARE(countItems(model), 40); +} + +void CompletionTest::testKateCompletionModel() +{ + KateCompletionModel *model = m_view->completionWidget()->model(); + CodeCompletionTestModel* testModel1 = new CodeCompletionTestModel(m_view, "aa"); + CodeCompletionTestModel* testModel2 = new CodeCompletionTestModel(m_view, "bb"); + + model->setCompletionModel(testModel1); + QCOMPARE(countItems(model), 40); + + model->addCompletionModel(testModel2); + QCOMPARE(countItems(model), 80); + + model->removeCompletionModel(testModel2); + QCOMPARE(countItems(model), 40); +} + +void CompletionTest::testAbortImmideatelyAfterStart() +{ + KateCompletionModel *model = m_view->completionWidget()->model(); + + CodeCompletionTestModel* testModel = new ImmideatelyAbortCompletionModel(m_view); + m_view->setCursorPosition(Cursor(0, 3)); + QVERIFY(!m_view->completionWidget()->isCompletionActive()); + emit m_view->userInvokedCompletion(); + QVERIFY(!m_view->completionWidget()->isCompletionActive()); +} + +#include "completion_test.moc" diff --git a/share/tests/completion_test.h b/share/tests/completion_test.h new file mode 100644 index 0000000..33f37ae --- /dev/null +++ b/share/tests/completion_test.h @@ -0,0 +1,61 @@ +/* This file is part of the KDE libraries + Copyright (C) 2008 Niko Sams + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_COMPLETIONTEST_H +#define KATE_COMPLETIONTEST_H + +#include + +namespace KTextEditor { + class Document; +} +class KateView; + +class CompletionTest : public QObject +{ + Q_OBJECT + + public: + CompletionTest() {} + virtual ~CompletionTest() {} + + private Q_SLOTS: + void init(); + void cleanup(); + void testFilterEmptyRange(); + void testFilterWithRange(); + void testCustomRange1(); + void testCustomRange2(); + void testCustomRangeMultipleModels(); + void testAbortCursorMovedOutOfRange(); + void testAbortInvalidText(); + void testAbortController(); + void testAbortControllerMultipleModels(); + void testEmptyFilterString(); + void testUpdateCompletionRange(); + void testCustomStartCompl(); + void testKateCompletionModel(); + void testAbortImmideatelyAfterStart(); + + private: + KTextEditor::Document* m_doc; + KateView *m_view; +}; + +#endif diff --git a/share/tests/encoding/cp1251.txt b/share/tests/encoding/cp1251.txt new file mode 100644 index 0000000..eaac632 --- /dev/null +++ b/share/tests/encoding/cp1251.txt @@ -0,0 +1,2 @@ +Testing + \ No newline at end of file diff --git a/share/tests/encoding/cyrillic_utf8.txt b/share/tests/encoding/cyrillic_utf8.txt new file mode 100644 index 0000000..51888b2 --- /dev/null +++ b/share/tests/encoding/cyrillic_utf8.txt @@ -0,0 +1,2 @@ +Testing +Тестовый текст раз два три \ No newline at end of file diff --git a/share/tests/encoding/kateencodingtest.cpp b/share/tests/encoding/kateencodingtest.cpp new file mode 100644 index 0000000..f62cfe2 --- /dev/null +++ b/share/tests/encoding/kateencodingtest.cpp @@ -0,0 +1,57 @@ +/* This file is part of the Kate project. + * + * Copyright (C) 2010 Christoph Cullmann + * Copyright (C) 2010 Dominik Haumann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "katetextbuffer.h" + +#include +#include + +int main (int argc, char *argv[]) +{ + // construct core app + QCoreApplication app (argc, argv); + + // get arguments + QString encoding = app.arguments().at(1); + QString inFile = app.arguments().at(2); + QString outFile = app.arguments().at(3); + + Kate::TextBuffer buffer (0); + + // set codec + buffer.setFallbackTextCodec (QTextCodec::codecForName ("ISO 8859-15")); + buffer.setTextCodec (QTextCodec::codecForName (encoding.toLatin1())); + + // switch to Mac EOL, this will test eol detection, as files are normal unix or dos + buffer.setEndOfLineMode (Kate::TextBuffer::eolMac); + + // load file + bool encodingErrors = false; + bool tooLongLines = false; + if (!buffer.load (inFile, encodingErrors, tooLongLines) || encodingErrors) + return 1; + + // save file + if (!buffer.save (outFile)) + return 1; + + return 0; +} diff --git a/share/tests/encoding/koi8-r.txt b/share/tests/encoding/koi8-r.txt new file mode 100644 index 0000000..eb61ad7 --- /dev/null +++ b/share/tests/encoding/koi8-r.txt @@ -0,0 +1,2 @@ +Testing + \ No newline at end of file diff --git a/share/tests/encoding/latin15.txt b/share/tests/encoding/latin15.txt new file mode 100644 index 0000000..974d9ab --- /dev/null +++ b/share/tests/encoding/latin15.txt @@ -0,0 +1,7 @@ +Test +Strae +Christoph +uerung +berall +Khler +$perlvar \ No newline at end of file diff --git a/share/tests/encoding/one-char-latin-15.txt b/share/tests/encoding/one-char-latin-15.txt new file mode 100644 index 0000000..92a39f3 --- /dev/null +++ b/share/tests/encoding/one-char-latin-15.txt @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/share/tests/encoding/utf16.txt b/share/tests/encoding/utf16.txt new file mode 100644 index 0000000..9c4a0ec Binary files /dev/null and b/share/tests/encoding/utf16.txt differ diff --git a/share/tests/encoding/utf16be.txt b/share/tests/encoding/utf16be.txt new file mode 100644 index 0000000..ec14d6a Binary files /dev/null and b/share/tests/encoding/utf16be.txt differ diff --git a/share/tests/encoding/utf32.txt b/share/tests/encoding/utf32.txt new file mode 100644 index 0000000..b234c06 Binary files /dev/null and b/share/tests/encoding/utf32.txt differ diff --git a/share/tests/encoding/utf32be.txt b/share/tests/encoding/utf32be.txt new file mode 100644 index 0000000..31e6e01 Binary files /dev/null and b/share/tests/encoding/utf32be.txt differ diff --git a/share/tests/encoding/utf8.txt b/share/tests/encoding/utf8.txt new file mode 100644 index 0000000..73c6f28 --- /dev/null +++ b/share/tests/encoding/utf8.txt @@ -0,0 +1,7 @@ +Test +Straße +Christoph +Äußerung +Überall +Köhler +$perlvar \ No newline at end of file diff --git a/share/tests/foldedselection_test.cpp b/share/tests/foldedselection_test.cpp new file mode 100644 index 0000000..27ab24f --- /dev/null +++ b/share/tests/foldedselection_test.cpp @@ -0,0 +1,80 @@ +/* This file is part of the Kate project. + * + * Copyright (C) 2012 Dominik Haumann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "foldedselection_test.h" + +#include + +#include +#include +#include +#include + +using namespace KTextEditor; + +QTEST_KDEMAIN(KateFoldedSelectionTest, GUI) + +void KateFoldedSelectionTest::initTestCase() +{ + KateGlobal::self()->incRef(); +} + +void KateFoldedSelectionTest::cleanupTestCase() +{ + KateGlobal::self()->decRef(); +} + +// +// when text is folded, and you set the text selection from top to bottom and +// type a character, the resulting text is borked. +// +// See https://bugs.kde.org/show_bug.cgi?id=295632 +// +void KateFoldedSelectionTest::foldedSelectionTest() +{ + KateDocument doc(false, false, false); + QString text = "oooossssssss\n" + "{\n" + "\n" + "}\n" + "ssssss----------"; + doc.setText(text); + doc.setHighlightingMode("C++"); + doc.buffer().ensureHighlighted (doc.lines()); + + // view must be visible... + KateView* view = static_cast(doc.createView(0)); + view->show(); + view->resize(400, 300); + + QTest::qWait(500); + doc.foldingTree()->collapseOne(1, 1); + QTest::qWait(500); + + view->setSelection(Range(Cursor(0,4), Cursor(4, 6))); + view->setCursorPosition(Cursor(4, 6)); + + QTest::qWait(500); + doc.typeChars(view, "x"); + QTest::qWait(500); + + QString line = doc.line(0); + QCOMPARE(line, QString("oooox----------")); +} diff --git a/share/tests/foldedselection_test.h b/share/tests/foldedselection_test.h new file mode 100644 index 0000000..ea2f3ee --- /dev/null +++ b/share/tests/foldedselection_test.h @@ -0,0 +1,36 @@ +/* This file is part of the KDE libraries + Copyright (C) 2012 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_FOLDED_SELECTION_TEST_H +#define KATE_FOLDED_SELECTION_TEST_H + +#include + +class KateFoldedSelectionTest : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + void foldedSelectionTest(); +}; + +#endif // KATE_FOLDED_SELECTION_TEST_H diff --git a/share/tests/folding-crash.py b/share/tests/folding-crash.py new file mode 100644 index 0000000..a072d68 --- /dev/null +++ b/share/tests/folding-crash.py @@ -0,0 +1,17 @@ +def foo: + return bar + +def foo: + """ text + text + text """ + +def foo: + if baz == None: + return default + return bar + +def foo: + if baz == None: + return default + return bar diff --git a/share/tests/hl/ejp1.asm b/share/tests/hl/ejp1.asm new file mode 100644 index 0000000..e161d4e --- /dev/null +++ b/share/tests/hl/ejp1.asm @@ -0,0 +1,285 @@ +; +; Decodeur de trame pulsadis EJP et préavis EJP +; (pic 12C508 ou 509) +; Alain Gibaud, 20-2-2001 +; +; ======================================================== + list r=hex,p=p12c508 + + include "p12c508.inc" +GP0 equ 0 +GP1 equ 1 +GP2 equ 2 +GP3 equ 3 +GP4 equ 4 +GP5 equ 5 +TO equ 4 +; masques pour acceder aux pattes +GP0bit equ 1 << GP0 +GP1bit equ 1 << GP1 +GP2bit equ 1 << GP2 +GP3bit equ 1 << GP3 +GP4bit equ 1 << GP4 +GP5bit equ 1 << GP5 +; ======================================================== +; affectation des pattes +; + +; sorties: (actives niv bas) +NORMAL equ GP0 ; LED verte +ALERTE equ GP1 ; LED orange +EJP equ GP2 ; LED rouge +; entrees:( actives niv bas) +SIGNAL equ GP3 ; avec pull-up, en provenance filtre 175 Hz +; GP4-5 sont utilisees par l'horloge +; ======================================================== +; variables: +TICKS equ 0x7 ; compteur de ticks (1 tick = 2/100 s) +SLOT equ 0x8 ; numero slot dans la trame +; ======================================================= +; Macros pour alleger le code ... +; +; Teste si min <= (var) < max +; branche en "in" si oui, en "out" si non. +; +Lminmax macro var,min,max,outm,in,outp + movlw min + subwf var,W ; (var) - min + btfss STATUS,C + goto outm ; C=0 => resutat < 0 => var < min + + movlw max + subwf var,W ; (var) - max + btfss STATUS,C + goto in + goto outp ; C=1 => resutat >= 0 => var >= min + endm +; +; Attend que le bit "bit" du registre "reg" soit a 1 +; +Waitbit1 macro reg,bit + local Wait1 +Wait1 btfss reg,bit + goto Wait1 + endm +; +; Attend que le bit "bit" du registre "reg" soit a 0 +; +Waitbit0 macro reg,bit + local Wait0 +Wait0 btfsc reg,bit + goto Wait0 + endm +; +; Branche en "label" si (reg) == num, sinon continue +; +Beq macro label,reg,num + movlw num + subwf reg,W + btfsc STATUS,Z + goto label + endm +; +; Branche en "label" si (reg) != num, sinon continue +; +Bne macro label,reg,num + movlw num + subwf reg,W + btfss STATUS,Z + goto label + endm + +; +; Branche en "label" si (reg) < num, sinon continue +; +Blt macro label,reg,num + movlw num + subwf reg,W ; reg - W + btfss STATUS,C + goto label ; C=0 => reg - W < 0 + endm + +; +; Branche en "label" si (reg) >= num, sinon continue +; +Bge macro label,reg,num + movlw num + subwf reg,W ; reg - W + btfsc STATUS,C + goto label ; C=1 => reg - W >= 0 + endm +; ======================================================== + ; CONFIG word ( en FFF ) + ; bits 11:5 don't care + ; bit 4 : MCLRE enabled = 1, tied to Vdd = 0 + ; bit 3 : code protection off = 1, on = 0 + ; bit 2 : no watchdog = 0, watchdog = 1 + ; bit 1-0 ; EXTRC = 00, INTRC = 10, XT = 01, LP = 00 + + __CONFIG B'000000001101' ; (horloge a quartz, avec watchdog) +; ======================================================== + org 0 + goto debut +;========================================================= +; sous-programmes +; ======================================================== +; regarde si le timer est passe a 0 +; si oui, le compteur de ticks est incremente +; et on attend le repassage a 1 +; Cette routine DOIT etre appelee tout les 2/100 s ou plus souvent +tickcount + clrwdt + movf TMR0,W + btfss STATUS,Z + retlw 0 + + incf TICKS,F +; attendre que le timer ait depasse 0 +waitnoZ + clrwdt + movf TMR0,W + btfsc STATUS,Z + goto waitnoZ + retlw 0 +; +; les 2 fct qui suivent maintiennent, le compteur de ticks +; (en plus de scruter une patte) +; attente d'un signal (logique negative) +waitsignal + call tickcount + btfsc GPIO,SIGNAL + goto waitsignal + retlw 0 +; attente fin signal +waitnosignal + call tickcount + btfss GPIO,SIGNAL + goto waitnosignal + retlw 0 +; remet a zero le compteur de ticks et le timer et le watchdog +clearticks + clrwdt + clrw + movwf TICKS + movwf TMR0 + ; pour eviter un timeout immediat, le timer est charge + ; a 1, et le 1er tick ne fait que 0.019922s au lieu de 0.2s + ; (ce n'est pas grave dans la mesure ou de toute facon, + ; le temps de traitement entre les different declenchements + ; de chrono n'est pas nul) + incf TMR0,F + retlw 0 + +; +; ========================================================== +; +debut + ; reset par Watchdog ? + btfsc STATUS,TO + goto notimeout + ; TO == 0 : OUI + clrwdt + goto 0x1FF ; recalibrage, 0x3FF sur 12C509 + + ; TO == 1 : NON +notimeout + movwf OSCCAL ; recalibrer l'horloge + clrf TMR0 ; RAZ timer + ; GPWU=1 : disable wake up on pin change + ; GPPU=0 : enable pullups (a voir avec le hard ..) + ; T0CS=0 : timer connected to F/4 + ; T0SE=x : dont't care + ; PSA=0 : prescaler assigned to timer + ; PS2-0= : timer prescaler 111= 1/256, 101 = 1/64, 011 = 1/16 + movlw B'10010101' + option + + ; config des pattes + movlw B'00001000' ; GP0-2 en sortie, GP3 entree + tris GPIO + + ; se mettre en mode normal + bcf GPIO,NORMAL + bsf GPIO,ALERTE + bsf GPIO,EJP + + +attendre_trame + call waitnosignal ; attendre ... + call waitsignal ; ... front montant + call clearticks + call waitnosignal + ; 45 tk = 0.9s, 55 tk = 1.1s + Lminmax TICKS,D'45',D'55',attendre_trame,pulse1s,attendre_trame +pulse1s + + ; attendre 162,5 tk = 2.75 s + 0.5 s = 3.25 s + call clearticks +again325 + call tickcount + Lminmax TICKS,D'162',D'162',again325,again325,end325 +end325 + + ; on est maintenant au centre du 1er bit + ; il suffit d'echantillonner toutes les 2.5s + movlw 1 + movwf SLOT + +sample btfsc GPIO,SIGNAL ; logique negative + goto slot40 + + ; signal detecte !! + Bne not5,SLOT,D'5' ; slot == 5 ? + ; oui - 5 = passage en alerte + bsf GPIO,NORMAL ; bit a 1 = LED eteinte + bsf GPIO,EJP ; bit a 1 = LED eteinte + bcf GPIO,ALERTE ; bit a 0 = LED allumee + goto nextslot +not5 + Bne not15,SLOT,D'15' ; slot == 15 ? + ; oui + btfsc GPIO,ALERTE ; deja en alerte ? + goto endejp + ; oui - 5 & 15 = debut ejp + bsf GPIO,NORMAL ; bit a 1 = LED eteinte + bsf GPIO,ALERTE ; bit a 1 = LED eteinte + bcf GPIO,EJP ; bit a 0 = LED allumee + goto nextslot +endejp + ; non - 15 seul = fin ejp + bsf GPIO,EJP ; bit a 1 = LED eteinte + bsf GPIO,ALERTE ; bit a 1 = LED eteinte + bcf GPIO,NORMAL ; bit a 0 = LED allumee + goto nextslot + +not15 +slot40 + ; slot 40 ? + Bne nextslot,SLOT,D'40' ; slot == 40 ? + ; et attendre une nouvelle trame + + goto attendre_trame +nextslot + incf SLOT,F + + ; si le signal est a 1, on en profite pour se resynchroniser + ; sur son front descendant, au cas ou l'emetteur ne soit pas + ; bien conforme au protocole. + btfss GPIO,SIGNAL + goto resynchro + ; attendre 125 ticks = 2.5s + call clearticks +again125 + call tickcount + Lminmax TICKS,D'125',D'126',again125,sample,again125 + +resynchro + call waitnosignal + call clearticks +again100 ; attente 2 s (100 ticks) + call tickcount + Lminmax TICKS,D'100',D'101',again100,sample,again100 + + end + + diff --git a/share/tests/hl/highlight.4th b/share/tests/hl/highlight.4th new file mode 100644 index 0000000..7465863 --- /dev/null +++ b/share/tests/hl/highlight.4th @@ -0,0 +1,187 @@ +( + + Example File for ANS Forth Syntax Highlighting + + 6th December 2011 Mark Corbin + + Version 1.0 06-12-11 + - Initial release. + +) + +\ This is a single line comment. + +( This +is +a +multi-line +comment ) + +\ Single Characters +char A +[char] B + +\ Strings +." Display this string." +s" Compile this string." +abort" This is an error message." +word parsethisstring +c" Compile another string." +parse parsethisstringtoo +.( Display this string too.) + +\ Constants and Variables +variable myvar +2variable mydoublevar +constant myconst +2constant mydoubleconst +value myval +20 to myval +fvariable myfloatvar +fconstant myfloatconst +locals| a b c d| + +\ Single Numbers +123 +-123 + +\ Double Numbers +123. +12.3 +-123. +-12.3 + + +\ Floating Point Numbers +1.2e3 +-1.2e3 +12e-3 ++12e-3 +-12e-3 ++12e+3 + +\ Keywords (one from each list) +dup +roll +flush +scr +dnegate +2rot +catch +abort +at-xy +time&date +file-size +rename-file +fround +fsincos +(local) +locals| | +allocate +words +assembler +search-wordlist +order +/string + + +\ Obsolete Keywords (one from each list) +tib +forget + +\ Simple Word Definition + +: square ( n1 -- n2 ) + dup \ Duplicate n1 on top of stack. + * \ Multiply values together leaving result n2. +; + +\ Words that Define New Words or Reference Existing Words + +create newword +marker newmarker +[compile] existingword +see existingword +code newcodeword +forget existingword + +\ Loop Constructs + +: squares ( -- ) + 10 0 do + i + dup + * + . + loop +; + +: forever ( -- ) + begin + ." This is an infinite loop." + again +; + + +variable counter +0 counter ! + +: countdown ( -- ) + begin + counter @ \ Fetch counter + dup . \ Display count value + 1- dup counter ! \ Decrement counter + 0= \ Loop until counter = 0 + until +; + +: countup ( -- ) + begin + counter @ \ Fetch counter + dup . \ Display count value + 10 + < + while + 1 counter +! \ Increment counter if < 10 + repeat +; + +\ Conditional Constructs + +: testnegative ( n -- ) + 0< if + ." Number is negative" + then +; + + +variable flag +0 flag ! + +: toggleflag ( -- ) + flag @ if \ Fetch flag and test + ." Flag is true." + 0 flag ! \ Set flag to false + else + ." Flag is false." + 1 flag ! \ Set flag to true + then +; + + +: translatenumber ( n -- ) + case + 1 of + ." Eins" + endof + 2 of + ." Zwei" + endof + 3 of + ." Drei" + endof + ." Please choose a number between 1 and 3." + endcase +; + +\ END OF FILE diff --git a/share/tests/hl/highlight.R b/share/tests/hl/highlight.R new file mode 100644 index 0000000..d0a50b6 --- /dev/null +++ b/share/tests/hl/highlight.R @@ -0,0 +1,239 @@ +all.equal <- function(target, current, ...) UseMethod("all.equal") + +all.equal.default <- + function(target, current, check.attributes = TRUE, ...) +{ + ## Really a dispatcher given mode() of args : + ## use data.class as unlike class it does not give "Integer" + if(is.language(target) || is.function(target) || is.environment(target)) + return(all.equal.language(target, current, ...)) + if(is.recursive(target)) + return(all.equal.list(target, current, ...)) + msg <- c(if(check.attributes) attr.all.equal(target, current, ...), + if(is.numeric(target)) { + all.equal.numeric(target, current, check.attributes = check.attributes, ...) + } else + switch (mode(target), + logical = , + complex = , + numeric = all.equal.numeric(target, current, check.attributes = check.attributes, ...), + character = all.equal.character(target, current, check.attributes = check.attributes, ...), + if(data.class(target) != data.class(current)) { + paste("target is ", data.class(target), ", current is ", + data.class(current), sep = "") + } else NULL)) + if(is.null(msg)) TRUE else msg +} + +all.equal.numeric <- + function(target, current, tolerance = .Machine$double.eps ^ .5, + scale = NULL, check.attributes = TRUE, ...) +{ + msg <- if(check.attributes) attr.all.equal(target, current, ...) + if(data.class(target) != data.class(current)) { + msg <- c(msg, paste("target is ", data.class(target), ", current is ", + data.class(current), sep = "")) + return(msg) + } + + lt <- length(target) + lc <- length(current) + cplx <- is.complex(target) + if(lt != lc) { + ## *replace* the 'Lengths' msg[] from attr.all.equal(): + if(!is.null(msg)) msg <- msg[- grep("\\bLengths\\b", msg)] + msg <- c(msg, paste(if(cplx)"Complex" else "Numeric", + ": lengths (", lt, ", ", lc, ") differ", sep = "")) + return(msg) + } + target <- as.vector(target) + current <- as.vector(current) + out <- is.na(target) + if(any(out != is.na(current))) { + msg <- c(msg, paste("'is.NA' value mismatches:", sum(is.na(current)), + "in current,", sum(out), " in target")) + return(msg) + } + out <- out | target == current + if(all(out)) { if (is.null(msg)) return(TRUE) else return(msg) } + + target <- target[!out] + current <- current[!out] + if(is.integer(target) && is.integer(current)) target <- as.double(target) + xy <- mean((if(cplx)Mod else abs)(target - current)) + what <- + if(is.null(scale)) { + xn <- mean(abs(target)) + if(is.finite(xn) && xn > tolerance) { + xy <- xy/xn + "relative" + } else "absolute" + } else { + xy <- xy/scale + "scaled" + } + + if(is.na(xy) || xy > tolerance) + msg <- c(msg, paste("Mean", what, if(cplx)"Mod", "difference:", format(xy))) + + if(is.null(msg)) TRUE else msg +} + +all.equal.character <- + function(target, current, check.attributes = TRUE, ...) +{ + msg <- if(check.attributes) attr.all.equal(target, current, ...) + if(data.class(target) != data.class(current)) { + msg <- c(msg, paste("target is ", data.class(target), ", current is ", + data.class(current), sep = "")) + return(msg) + } + lt <- length(target) + lc <- length(current) + if(lt != lc) { + if(!is.null(msg)) msg <- msg[- grep("\\bLengths\\b", msg)] + msg <- c(msg, paste("Lengths (", lt, ", ", lc, + ") differ (string compare on first ", ll <- min(lt, lc), + ")", sep = "")) + ll <- seq(length = ll) + target <- target[ll] + current <- current[ll] + } + nas <- is.na(target) + if (any(nas != is.na(current))) { + msg <- c(msg, paste("'is.NA' value mismatches:", sum(is.na(current)), + "in current,", sum(nas), " in target")) + return(msg) + } + ne <- !nas & (target != current) + if(!any(ne) && is.null(msg)) TRUE + else if(any(ne)) c(msg, paste(sum(ne), "string mismatches")) + else msg +} + +all.equal.factor <- function(target, current, check.attributes = TRUE, ...) +{ + if(!inherits(current, "factor")) + return("'current' is not a factor") + msg <- if(check.attributes) attr.all.equal(target, current) + class(target) <- class(current) <- NULL + nax <- is.na(target) + nay <- is.na(current) + if(n <- sum(nax != nay)) + msg <- c(msg, paste("NA mismatches:", n)) + else { + target <- levels(target)[target[!nax]] + current <- levels(current)[current[!nay]] + if(is.character(n <- all.equal(target, current, check.attributes = check.attributes))) + msg <- c(msg, n) + } + if(is.null(msg)) TRUE else msg +} + +all.equal.formula <- function(target, current, ...) +{ + if(length(target) != length(current)) + return(paste("target, current differ in having response: ", + length(target) == 3, ", ", length(current) == 3)) + if(all(deparse(target) != deparse(current))) + "formulas differ in contents" + else TRUE +} + +all.equal.language <- function(target, current, check.attributes = TRUE, ...) +{ + mt <- mode(target) + mc <- mode(current) + if(mt == "expression" && mc == "expression") + return(all.equal.list(target, current, check.attributes = check.attributes, ...)) + ttxt <- paste(deparse(target), collapse = "\n") + ctxt <- paste(deparse(current), collapse = "\n") + msg <- c(if(mt != mc) + paste("Modes of target, current: ", mt, ", ", mc, sep = ""), + if(ttxt != ctxt) { + if(pmatch(ttxt, ctxt, FALSE)) + "target a subset of current" + else if(pmatch(ctxt, ttxt, FALSE)) + "current a subset of target" + else "target, current don't match when deparsed" + }) + if(is.null(msg)) TRUE else msg +} + +all.equal.list <- function(target, current, check.attributes = TRUE, ...) +{ + msg <- if(check.attributes) attr.all.equal(target, current, ...) +## nt <- names(target) +## nc <- names(current) + iseq <- + ## + ## Commenting this eliminates PR#674, and assumes that lists are + ## regarded as generic vectors, so that they are equal iff they + ## have identical names attributes and all components are equal. + ## if(length(nt) && length(nc)) { + ## if(any(not.in <- (c.in.t <- match(nc, nt, 0)) == 0)) + ## msg <- c(msg, paste("Components not in target:", + ## paste(nc[not.in], collapse = ", "))) + ## if(any(not.in <- match(nt, nc, 0) == 0)) + ## msg <- c(msg, paste("Components not in current:", + ## paste(nt[not.in], collapse = ", "))) + ## nt[c.in.t] + ## } else + ## + if(length(target) == length(current)) { + seq(along = target) + } else { + if(!is.null(msg)) msg <- msg[- grep("\\bLengths\\b", msg)] + nc <- min(length(target), length(current)) + msg <- c(msg, paste("Length mismatch: comparison on first", + nc, "components")) + seq(length = nc) + } + for(i in iseq) { + mi <- all.equal(target[[i]], current[[i]], check.attributes = check.attributes, ...) + if(is.character(mi)) + msg <- c(msg, paste("Component ", i, ": ", mi, sep="")) + } + if(is.null(msg)) TRUE else msg +} + + +attr.all.equal <- function(target, current, + check.attributes = TRUE, check.names = TRUE, ...) +{ + ##--- "all.equal(.)" for attributes --- + ##--- Auxiliary in all.equal(.) methods --- return NULL or character() + msg <- NULL + if(mode(target) != mode(current)) + msg <- paste("Modes: ", mode(target), ", ", mode(current), sep = "") + if(length(target) != length(current)) + msg <- c(msg, paste("Lengths: ", length(target), ", ", + length(current), sep = "")) + ax <- attributes(target) + ay <- attributes(current) + if(check.names) { + nx <- names(target) + ny <- names(current) + if((lx <- length(nx)) | (ly <- length(ny))) { + ## names() treated now; hence NOT with attributes() + ax$names <- ay$names <- NULL + if(lx && ly) { + if(is.character(m <- all.equal.character(nx, ny, check.attributes = check.attributes))) + msg <- c(msg, paste("Names:", m)) + } else if(lx) + msg <- c(msg, "names for target but not for current") + else msg <- c(msg, "names for current but not for target") + } + } + if(check.attributes && (length(ax) || length(ay))) {# some (more) attributes + ## order by names before comparison: + nx <- names(ax) + ny <- names(ay) + if(length(nx)) ax <- ax[order(nx)] + if(length(ny)) ay <- ay[order(ny)] + tt <- all.equal(ax, ay, check.attributes = check.attributes, ...) + if(is.character(tt)) msg <- c(msg, paste("Attributes: <", tt, ">")) + } + msg # NULL or character +} + diff --git a/share/tests/hl/highlight.abc b/share/tests/hl/highlight.abc new file mode 100644 index 0000000..a7e45f7 --- /dev/null +++ b/share/tests/hl/highlight.abc @@ -0,0 +1,8 @@ +% Taken from http://www.gre.ac.uk/~c.walshaw/abc/#examples +T:Paddy O'Rafferty +C:Trad. +M:6/8 +K:D +dff cee|def gfe|dff cee|dfe dBA|dff cee|def gfe|faf gfe|1 dfe dBA:|2 dfe dcB|| +~A3 B3|gfe fdB|AFA B2c|dfe dcB|~A3 ~B3|efe efg|faf gfe|1 dfe dcB:|2 dfe dBA|| +fAA eAA|def gfe|fAA eAA|dfe dBA|fAA eAA|def gfe|faf gfe|dfe dBA:| diff --git a/share/tests/hl/highlight.ahdl b/share/tests/hl/highlight.ahdl new file mode 100644 index 0000000..e059aa8 --- /dev/null +++ b/share/tests/hl/highlight.ahdl @@ -0,0 +1,43 @@ +-- Test file for kate's syntax highlighting +Title "Test file"; + +-- BEGIN region (a region marker region) :) + +% multiline comment +goes on here % + +-- END + +FUNCTION FCT (Clk, Key) RETURNS (pulse); + +SUBDESIGN CDCLOCK2 +( +in : INPUT; -- go in +out[3..0] : OUTPUT; -- come out +) + +VARIABLE +start : soft; +usec[3..0] : node; + +BEGIN + +in = FCT(clock, some_key); -- senseless code + +-- comment +blubb = (blobb[] == H"3ff"); + +IF in THEN asdf +-- folde me +END IF; + +TABLE +-- missing code +END TABLE + + +END; + +-- hex, octal, binary +H"0" => B"1000000"; +O"01234567"; \ No newline at end of file diff --git a/share/tests/hl/highlight.asm-avr b/share/tests/hl/highlight.asm-avr new file mode 100644 index 0000000..f1e0542 --- /dev/null +++ b/share/tests/hl/highlight.asm-avr @@ -0,0 +1,75 @@ +;******************************************************************** +;* LED flasher: LED will flash with a X on/off ratio at PD6 +;* +;* NOTE: delay depends in the value of X, 1 is fast, 255 is slow +;* +;* No copyright ©1998 RES® * FREEWARE * +;* +;* NOTE: Connect a low current LED with a 1k resistor in serie from +;* Vdd to pin 11 of the MCU. (Or a normal LED with a 330ohm) +;* +;* RES® can be reached by email: digitalaudio@mail.com +;* or visit the website: http://home.wanadoo.nl/electro1/avr +;* +;* Version :1.0 +;* Date :12/26/98 +;* Author :Rob's ElectroSoft® +;* Target MCU :AT90S1200-12PI@4MHz +;******************************************************************** + +.include "1200def.inc" + + rjmp RESET ;reset handle + + +;* Long delay + +;* Register variables + + .def T1 = r1 + .def T2 = r2 + .def temp = r19 + +;* Code + +longDelay: + clr T1 ;T1 used as delay 2nd count + clr T2 ;T2 used as delay 3d count +delay_1: + dec T2 + brne delay_1 + dec T1 + brne delay_1 + dec temp ;temp must be preset as + brne delay_1 ; delay master count + ret + + +;* Resets the data direction register D + +;* Defines + + .equ led = 6 ;LED at PD6 + +;* Code + +RESET: + sbi DDRD, led ;connect LED to PORTD pin 6 + + +;* Main program + +;* This part will let the LED go on and off by X + +;* Register variables + + .equ X = 10 ;enter delaytime X + +flash: + sbi PORTD, led ;LED on + ldi temp, X ;X sec delay + rcall longDelay + cbi PORTD, led ;LED off + ldi temp, X ;X sec delay + rcall longDelay + rjmp flash ;another run \ No newline at end of file diff --git a/share/tests/hl/highlight.asm-nasm b/share/tests/hl/highlight.asm-nasm new file mode 100644 index 0000000..a5da4d1 --- /dev/null +++ b/share/tests/hl/highlight.asm-nasm @@ -0,0 +1,27 @@ +; Example file for nasm.xml kate syntax file +; compile with `nasm example.asm -f elf -o example.o` +; and link with 'gcc example.o -o example` +; Public domain +; kate: hl Intel x86 (NASM); + +section .data + +hello dd 'Hello World', 0x0A, 0h +printf_param dd '%s', 0q + +section .text + +extern printf + +global main +main: + push ebp + mov ebp, esp + + push hello + push printf_param + call printf + + mov eax, 0b + leave + ret diff --git a/share/tests/hl/highlight.asp b/share/tests/hl/highlight.asp new file mode 100644 index 0000000..7f4fe90 --- /dev/null +++ b/share/tests/hl/highlight.asp @@ -0,0 +1,64 @@ +<% 'kate: hl ASP; +if ( instr(request.servervariables("PATH_INFO"),"login.asp") <= 0 and instr(request.servervariables("PATH_INFO"),"inset") <= 0 and instr(request.servervariables("PATH_INFO"),"Data") <= 0 and instr(request.servervariables("PATH_INFO"),"dropDown") <= 0 ) then + Session("originalRequestedPage") = Request.ServerVariables("PATH_INFO") & "?" & Request.ServerVariables("QUERY_STRING") +end if + +function countRecords( rsToCount ) + numRecs = 0 + + do until rsToCount.eof + numRecs = numRecs + 1 + + rsToCount.movenext + loop + + do while rsToCount.eof + numRecs = numRecs + 1 + + rsToCount.movenext + loop + + rsToCount.close ' just to make sure nobody + ' tries to operate on the recordset, + ' which has already reached eof + + countRecords = numRecs +end function + +function unique( rs, sortColumn ) ' return unique instances of text in sortColumn within rs + dim sorted() + + redim sorted(1) + dim i + i = 0 + do until rs.eof + if (not find( rs(sortColumn), sorted )) then + redim preserve sorted(i+1) + sorted(i) = rs(sortColumn) + i = i + 1 + end if + rs.MoveNext + loop + + redim preserve sorted(i-1) ' the function will add an extra blank entry to the array + + rs.Close ' close the recordset - we'll be using it again - and reset i - well be using it again, too + + unique = sorted +end function + +sub testSub( variable ) ' do nothing impressive... + dim newVar + + newVar = variable + + if ( variable = true ) + response.end + else %> + +

We are writing text.

+

<%=newVar%>

+

We have written text and outputted a variable.

+ +<% end if +end sub %> \ No newline at end of file diff --git a/share/tests/hl/highlight.awk b/share/tests/hl/highlight.awk new file mode 100644 index 0000000..47f10cf --- /dev/null +++ b/share/tests/hl/highlight.awk @@ -0,0 +1,28 @@ +#!/usr +# AWK hl test + +# BEGIN and END are also matched as patterns +BEGIN { + p = 0; +} + +/some pattern/ { + p++; +} + +# / inside brackets is not considered end of expression +# a loose division operator (/) is not mismatched as a pattern. +$1 =~ /[^abc/]def/ || b == 3 / 5 { + + gsub ( FILENAME ); + +} + +# TODO and FIXME also work in comments in Awk. + +# Also backslash in patterns works. +/\/usr\/bin\/awk/ { print "This is me"; } + +END { + print p; +} diff --git a/share/tests/hl/highlight.bib b/share/tests/hl/highlight.bib new file mode 100644 index 0000000..0ae404c --- /dev/null +++ b/share/tests/hl/highlight.bib @@ -0,0 +1,31 @@ +% test file for kate's bibtex syntax highlighting + +@Article{artikel, +author = {Me}, +title = {Something}, +journal = {JHEP}, +year = {2003}, +} + +@Book + +{ + +boek, +author = "Someone", +title = "Something", +journal = "Nucl. Phys. B", +year = "2003", +} + +This is ignored by BibTeX, no special highlighting +%This is not a comment, it is just ignored (thanks to the people in #latex) :) + +@string{test="lange string die ik niet vaak opnieuw wil intikken"} + +@PhdThesis{thesis, +author = {Me}, +title = {Dunno}, +school = {ITFA}, +year = {2005, hopefully}, +} diff --git a/share/tests/hl/highlight.clj b/share/tests/hl/highlight.clj new file mode 100644 index 0000000..2569b15 --- /dev/null +++ b/share/tests/hl/highlight.clj @@ -0,0 +1,182 @@ +(ns compojure.core + "A concise syntax for generating Ring handlers." + (:require [clojure.string :as str]) + (:use clout.core + compojure.response + [clojure.core.incubator :only (-?>)] + [clojure.tools.macro :only (name-with-attributes)])) + +(defn- method-matches? + "True if this request matches the supplied request method." + [method request] + (let [request-method (request :request-method) + form-method (get-in request [:form-params "_method"])] + (if (and form-method (= request-method :post)) + (= (str/upper-case (name method)) form-method) + (= method request-method)))) + +(defn- if-method + "Evaluate the handler if the request method matches." + [method handler] + (fn [request] + (cond + (or (nil? method) (method-matches? method request)) + (handler request) + (and (= :get method) (= :head (:request-method request))) + (-?> (handler request) + (assoc :body nil))))) + +(defn- assoc-route-params + "Associate route parameters with the request map." + [request params] + (merge-with merge request {:route-params params, :params params})) + +(defn- if-route + "Evaluate the handler if the route matches the request." + [route handler] + (fn [request] + (if-let [params (route-matches route request)] + (handler (assoc-route-params request params))))) + +(defn- prepare-route + "Pre-compile the route." + [route] + (cond + (string? route) + `(route-compile ~route) + (vector? route) + `(route-compile + ~(first route) + ~(apply hash-map (rest route))) + :else + `(if (string? ~route) + (route-compile ~route) + ~route))) + +(defn- assoc-&-binding [binds req sym] + (assoc binds sym `(dissoc (:params ~req) + ~@(map keyword (keys binds)) + ~@(map str (keys binds))))) + +(defn- assoc-symbol-binding [binds req sym] + (assoc binds sym `(get-in ~req [:params ~(keyword sym)] + (get-in ~req [:params ~(str sym)])))) + +(defn- vector-bindings + "Create the bindings for a vector of parameters." + [args req] + (loop [args args, binds {}] + (if-let [sym (first args)] + (cond + (= '& sym) + (recur (nnext args) (assoc-&-binding binds req (second args))) + (= :as sym) + (recur (nnext args) (assoc binds (second args) req)) + (symbol? sym) + (recur (next args) (assoc-symbol-binding binds req sym)) + :else + (throw (Exception. (str "Unexpected binding: " sym)))) + (mapcat identity binds)))) + +(defmacro let-request [[bindings request] & body] + (if (vector? bindings) + `(let [~@(vector-bindings bindings request)] ~@body) + `(let [~bindings ~request] ~@body))) + +(defn- compile-route + "Compile a route in the form (method path & body) into a function." + [method route bindings body] + `(#'if-method ~method + (#'if-route ~(prepare-route route) + (fn [request#] + (let-request [~bindings request#] + (render (do ~@body) request#)))))) + +(defn routing + "Apply a list of routes to a Ring request map." + [request & handlers] + (some #(% request) handlers)) + +(defn routes + "Create a Ring handler by combining several handlers into one." + [& handlers] + #(apply routing % handlers)) + +(defmacro defroutes + "Define a Ring handler function from a sequence of routes. The name may + optionally be followed by a doc-string and metadata map." + [name & routes] + (let [[name routes] (name-with-attributes name routes)] + `(def ~name (routes ~@routes)))) + +(defmacro GET "Generate a GET route." + [path args & body] + (compile-route :get path args body)) + +(defmacro POST "Generate a POST route." + [path args & body] + (compile-route :post path args body)) + +(defmacro PUT "Generate a PUT route." + [path args & body] + (compile-route :put path args body)) + +(defmacro DELETE "Generate a DELETE route." + [path args & body] + (compile-route :delete path args body)) + +(defmacro HEAD "Generate a HEAD route." + [path args & body] + (compile-route :head path args body)) + +(defmacro ANY "Generate a route that matches any method." + [path args & body] + (compile-route nil path args body)) + +(defn- remove-suffix [path suffix] + (subs path 0 (- (count path) (count suffix)))) + +(defn- wrap-context [handler] + (fn [request] + (let [uri (:uri request) + path (:path-info request uri) + context (or (:context request) "") + subpath (-> request :route-params :__path-info)] + (handler + (-> request + (assoc :path-info (if (= subpath "") "/" subpath)) + (assoc :context (remove-suffix uri subpath)) + (update-in [:params] dissoc :__path-info) + (update-in [:route-params] dissoc :__path-info)))))) + +(defn- context-route [route] + (let [re-context {:__path-info #"|/.*"}] + (cond + (string? route) + `(route-compile ~(str route ":__path-info") ~re-context) + (vector? route) + `(route-compile + ~(str (first route) ":__path-info") + ~(merge (apply hash-map (rest route)) re-context))))) + +(defmacro context + "Give all routes in the form a common path prefix and set of bindings. + + The following example demonstrates defining two routes with a common + path prefix ('/user/:id') and a common binding ('id'): + + (context \"/user/:id\" [id] + (GET \"/profile\" [] ...) + (GET \"/settings\" [] ...))" + [path args & routes] + `(#'if-route ~(context-route path) + (#'wrap-context + (fn [request#] + (let-request [~args request#] + (routing request# ~@routes)))))) + +(defmacro let-routes + "Takes a vector of bindings and a body of routes. Equivalent to: + (let [...] (routes ...))" + [bindings & body] + `(let ~bindings (routes ~@body))) diff --git a/share/tests/hl/highlight.css b/share/tests/hl/highlight.css new file mode 100644 index 0000000..986c6c0 --- /dev/null +++ b/share/tests/hl/highlight.css @@ -0,0 +1,49 @@ +/** + * This is a pseudo CSS file to test Kate's CSS syntax highlighting. + */ + +@import url("othersheet.css") screen, tv; + +body { + font-size: 15pt; + font-family: Verdana, Helvetica, "Bitstream Vera Sans", sans-serif; + margin-top: 0px; /* yet another comment */ + margin-bottom: 0px; + // this is no comment, it's just broken! + margin-left: 0px; + margin-right: 0px; +} + +.something +{ + margin-right: 0px; + color: #cdd; + color: #AAFE04; + color: rgb(10%,30%,43%); + background: maroon; +} + +a:hover { +} + +#header, +p.intro:first-letter, +p:lang(nl), +img[align="right"] +{ + border: 1px solid Qt::red !important; + -moz-border-radius: 15px; /* unknown properties render italic */ +} + +@media print { + + #header + { + display: none; + } + +} + +/* +TODO: add more tests, e.g. media +*/ diff --git a/share/tests/hl/highlight.d b/share/tests/hl/highlight.d new file mode 100644 index 0000000..b3daaf6 --- /dev/null +++ b/share/tests/hl/highlight.d @@ -0,0 +1,195 @@ +/******** +* Highlight testing module. +* +* Do not attempt to run this! +***********/ +module highlighttest; +import X = null; + +/++ Pragma directives. DDoc + DDoc embedded items. Special Tokens. ++ ++ --- ++ // comment ++ #line 12 "hightlighttest.d" /* block comment */ ++ #line __LINE__ __FILE__ /++ embedded block comment +/ ++ ++ pragma /* */ (msg, "what?"); ++ pragma(/++ +/ lib, "insane.a"); ++ pragma(D_Custom_Extension, "custom data"); ++ --- ++/ + +/// version condition +version = X; +version (X) ; +version(linux) {} + +/// linkage +extern + (C) {} +extern : +; +extern (Windows) {} + +/// alias & typedef +alias int.min minint; +typedef int myint; + +int main(char[][] args) { + /// statements + if (1) {} + else {} + with (N) {x = B} + + /// attributes + auto x = 1; + static if (true) {} + void (in X, out Y) {} // NOTE: using in like this is rare, more common to use as an expression and no way to tell apart? + + /// deprecated + deprecated void fct (); + + /// types + void a; + ushort u; + int[uint] AA; + class C; + enum N : int { A = 5, B } + typeof(u) u2; + + /// expressions + x = cast(int) 55; + void* p = null; + p = cast(void*) new int; + x = 1 in AA; // NOTE: a THIRD use of in. How to detect?? + assert (true); + + /// libsymbols + string s = ""; + throw new Exception; + TypeInfo ti = typeid(int); + + /// tests + debug {} + debug (2) {} + debug (DSymb) {} + unittest {} + + /// scope (as attribute and as statement) + scope struct S; + scope (exit) {} + scope + (success) {} // NOTE: rules cannot match across new-lines + scope (failure) {} + + /// Properties + x = int.min; + s = (5-3).stringof; + + /// strings + s = r"raw string"; + s = x"00FF"; + s = \n \a; + s = \u1234; + s = \U12345678; + s = \& ; + char c = 'a'; + s = "abc 012 \" \n \x12 \u1234 \U12345678"; + s = `BQString '"`; + + /// region markers + //BEGIN x + //END x + + /// DDoc + /******* + * DDoc + * + * Section: + * New section. + * $(I italic) + *******/ + /+++++++ + + DDoc + + /+ + + +/ + +++++++/ + + // comments + // FIXME NOTE + /* comment */ + /+ comment /+ nested comment +/ +/ + + /// brace folding + { + } + + /** normal text + * --- + * .x; + * .. + * ... + * .... + * ..... + * _._ + * _e1 + * --- + */ + + /// float and int literals + int i; + real r; + ireal ir; + r = .0; + r = 0f; + ir = 0e0i; + ir = 0.fi; + r = 0.0e0; + r = 0xF.Fp0; + r = 0x_._p0_; + i = 5; + i = -1; + i = 0b10; + i = 0070; + i = 00; + i = 0xF0; + + /// ranges + int[] A; + i = A[1]; + A = A[0..$]; + A = A[0..0]; + A = A[0..length]; + + /// labels + label: + goto label; + + /// function, delegate + creal function () fp = function creal() { return 0f+0fi; }; + void delegate (in int i, lazy int b) dg = delegate void (int, int) {} + + /// in, out, body + // NOTE: highlighting in & out as statements here could be difficult + float F () + in {} + out (result) {} + body {} + + /// try, catch, finally + try { + throw new Exception("oh no... "); + } catch (Exception e) { + } finally { + } + + /// mixin + mixin("return false;").stringof; + + /// templates + macro; // what does this do? + template Tp (T) { + Tp t; + } + Tp!(int) y; +} diff --git a/share/tests/hl/highlight.do b/share/tests/hl/highlight.do new file mode 100644 index 0000000..0b90b16 --- /dev/null +++ b/share/tests/hl/highlight.do @@ -0,0 +1,89 @@ +/* Test file for kate's stata syntax highlighting +*/ +*! version 1.2.0 2mar2003 E. Leuven +program define spellsplit + version 7 + syntax [anything], spell(varlist min=2 max=2) [ by(varlist)] + tokenize `spell' + local date0 `1' + local date1 `2' + local f0 : format `date0' + local f1 : format `date1' + + /* set default statistic */ + local current "mean" + + gettoken left anything : anything, match(prns) + while "`left'"!="" { + if "`prns'"!="" { + if !inlist("`left'","mean","sum") { + di as error "Statistic `left' not supported" + exit 198 + } + local current "`left'" + } + else { + local `current'vars ``current'vars' `left' + } + gettoken left anything : anything, match(prns) + } + if ("`meanvars'"!="") { + confirm var `meanvars' + unab meanvars : `meanvars' + } + if ("`sumvars'"!="") { + confirm var `sumvars' + unab sumvars : `sumvars' + } + + quietly { + g _count = 1 + local xvars `meanvars' `sumvars' _count + + /* create dummy by-var if no by option is specified */ + if "`by'"=="" { + tempvar by + g byte `by' = 1 + } + tempvar `xvars' `by' + + /* create negative for subtraction when spell ends */ + cap foreach v of varlist `xvars' { + g double ``v'' = -`v' + local txvars `txvars' ``v'' + } + cap foreach v of varlist `by' { + g double ``v'' = `v' + local txvars `txvars' ``v'' + } + + stack `date0' `xvars' `by' `date1' `txvars', into(`date0' `xvars' `by') clear + + /* calculate totals per date */ + cap foreach v of varlist `xvars' { + egen double ``v'' = sum(`v'), by(`by' `date0') + } + + /* unique dates only */ + by `by' `date0', sort: keep if _n==1 + + /* calculate totals (+ when spell starts - when ends) */ + sort `by' + cap foreach v of varlist `xvars' { + by `by': replace `v' = sum(``v'') + } + by `by': g `date1' = `date0'[_n + 1] + + drop if `date0'>`date1' + drop _stack + drop if _count==0 + order `by' `date0' `date1' `xvars' + format `date0' `f0' + format `date1' `f1' + + cap for var `meanvars': replace X = X/_count + + compress + } + +end \ No newline at end of file diff --git a/share/tests/hl/highlight.dox b/share/tests/hl/highlight.dox new file mode 100644 index 0000000..39b404f --- /dev/null +++ b/share/tests/hl/highlight.dox @@ -0,0 +1,227 @@ +This is a pseudo doxygen file to test Kate's doxyge syntax highlighting. + +Normal text, no HL. +=================== +a multiline comment may begin with a /*! */, too. That should work, +because it is the same "entrance rule". + +popping tests: +/** multiline */ end of doxygen HL mode +/*! multiline */ end of doxygen HL mode +//! singleline, where */ should be ignored! still doxygen HL mode +/// singleline, where */ should be ignored! still doxygen HL mode +///< singleline, where */ should be ignored! still doxygen HL mode +begin and end immediately: +/********/ actually no doxygen comment - used for "info boxes" :) +/**/ <-- it really works --- end of doxygen HL mode +/*!*/ end of doxygen HL mode + + +/** \code rest of line is normal comment HL */ end of doxygen HL mode +/** \code rest of line is normal comment HL + * comment HL mode + */ end of doxygen HL mode + + +/** \file aword rest of line is normal comment HL */ end of doxygen HL mode +/** \file */aword <-- pop! no doxygen HL mode +/** \file aword rest of line is normal comment HL + * comment HL mode + */ end of doxygen HL mode + + +/** \brief A short description */ end of doxygen HL mode +/** \brief */A <-- pop! end of doxygen HL mode +/** \brief A short description + * comment HL mode + */ end of doxygen HL mode + + +/** \page aword rest of line is string */ end of doxygen HL mode +/** \page */aword <-- pop! end of doxygen HL mode +/** \page aword rest of line is string + * comment HL mode + */ end of doxygen HL mode + + +/** \image aword aword rest of line is normal HL */ end of doxygen HL mode +/** \image aword */aword <-- pop! end of doxygen HL mode +/** \image */aword aword <-- pop! end of doxygen HL mode +/** \image aword aword rest of line is normal HL + * comment HL mode + */ end of doxygen HL mode + +Tests for HTML tags in doxygen HL mode: +======================================= +/** */ end of doxygen HL mode +/** end of doxygen HL mode +/** end of doxygen HL mode +/** end of doxygen HL mode +/** end of doxygen HL mode +/** end of doxygen HL mode +/** end of doxygen HL mode +/** end of doxygen HL mode +/** end of doxygen HL mode +/** end of doxygen HL mode +/** */ end of doxygen HL mode +/** end of doxygen HL mode +/** end of doxygen HL mode +/** end of doxygen HL mode +/** end of doxygen HL mode +/** end of doxygen HL mode +/** end of doxygen HL mode +/** end of doxygen HL mode +/** end of doxygen HL mode +/** end of doxygen HL mode +/** <*/a href="blubb"> end of doxygen HL mode + +//! */ stay in doygen HL mode +//! stay in doygen HL mode +//! stay in doygen HL mode +//! stay in doygen HL mode +//! stay in doygen HL mode +//! stay in doygen HL mode +//! */ stay in doygen HL mode +//! stay in doygen HL mode +//! stay in doygen HL mode +//! stay in doygen HL mode +//! stay in doygen HL mode +//! stay in doygen HL mode +//! stay in doygen HL mode +//! stay in doygen HL mode +//! stay in doygen HL mode +//! stay in doygen HL mode +//! <*/a href="blubb"> stay in doygen HL mode +//! stay in doygen HL +/** \code rest of line is normal comment HL */ end of doxygen HL mode +/** \code rest of end of doxygen HL mode +/** \code rest of end of doxygen HL mode +/** \code rest of end of doxygen HL mode +/** \code rest of end of doxygen HL mode +/** \code rest of end of doxygen HL mode +/** \code rest of end of doxygen HL mode +/** \code rest of end of doxygen HL mode +/** \code rest <*/a href="blubb"> of end of doxygen HL mode +/** \code rest of line is normal comment HL + * comment HL mode text + */ end of doxygen HL mode + + +/** \file aword rest of line is normal comment HL */ end of doxygen HL mode +/** \file awo*/rd end of doxygen HL mode +/** \file aword end of doxygen HL mode +/** \file awo<*/html_should_be_ignored_here>rd end of doxygen HL mode +/** \file a*/word end of doxygen HL mode +/** \file aword rest of line is normal comment HL + * comment HL mode + */ end of doxygen HL mode + + +/** \brief A short of description */ end of doxygen HL mode +/** \brief A short of end of doxygen HL mode +/** \brief A short of end of doxygen HL mode +/** \brief A short of end of doxygen HL mode +/** \brief A short of end of doxygen HL mode +/** \brief A short of end of doxygen HL mode +/** \brief A short of <*//a href='blubb'> end of doxygen HL mode +/** \brief A short of end of doxygen HL mode +/** \brief A short of end of doxygen HL mode +/** \brief A short of end of doxygen HL mode +/** \brief A short of end of doxygen HL mode +/** \brief A short of end of doxygen HL mode +/** \brief A short of end of doxygen HL mode +/** \brief A short of description + * comment HL mode + */ end of doxygen HL mode + + +/** \page aword A short of description */ end of doxygen HL mode +/** \page aword A short of end of doxygen HL mode +/** \page aword A short of end of doxygen HL mode +/** \page aword A short of end of doxygen HL mode +/** \page aword A short of end of doxygen HL mode +/** \page aword A short of end of doxygen HL mode +/** \page aword A short of <*//a href='blubb'> end of doxygen HL mode +/** \page aword A short of end of doxygen HL mode +/** \page aword A short of end of doxygen HL mode +/** \page aword A short of end of doxygen HL mode +/** \page aword A short of end of doxygen HL mode +/** \page aword A short of end of doxygen HL mode +/** \page aword A short of end of doxygen HL mode +/** \page aword A short <*/a href="blubb"> of end of doxygen HL mode +/** \page aword A shor*/t of end of doxygen HL mode +/** \page awor*/d A short of end of doxygen HL mode +/** \page */aword A short of end of doxygen HL mode +/** \page aword A short of description + * comment HL mode + */ end of doxygen HL mode + + +/** \image aword aword rest of line is normal HL */ end of doxygen HL mode +/** \image aword aword rest of line is*/ end of doxygen HL mode +/** \image aword aword*/ end of doxygen HL mode +/** \image aword aw*/ord end of doxygen HL mode +/** \image aword */aword end of doxygen HL mode +/** \image aword*/ end of doxygen HL mode +/** \image awo*/rd end of doxygen HL mode +/** \image */aword end of doxygen HL mode +/** \ima*/ge end of doxygen HL mode +/** \image aword aword rest of line is normal HL + * comment HL mode + */ end of doxygen HL mode + +Some further tests for singlelinecomments (* / should not pop!) +=============================================================== +/// a singlelinecommment blubb blubb */. stay in doxygen HL mode +/// \code a singlelinecommment blubb b*/lubb. stay in doxygen HL mode +/// \code*/ a singlelinecommment blubb blubb. stay in doxygen HL mode +/// \code a singlelinecommment blubb blubb +/// \brief a descriptive text (string) stay in doxygen HL mode +/// \brief a descriptive text (string)*/ description should go on here +/// \brief a descriptive text */(string) description should go on here +/// \brief */a descriptive text (string) description should go on here +/// \ref aword a descriptive text (string) */ description should go on here +/// \ref aword a descriptive text (str*/ing) description should go on here +/// \ref aword a des*/criptive text (string) description should go on here +/// \ref aword*/ a descriptive text (string) description should go on here +/// \ref aw*/ord a descriptive text (string) description should go on here +/// \ref */aword a descriptive text (string) description should go on here + +HTML comment tests: +=================== +//! \ref word descriptive text (string) +normal HL mode. +//! \ref w descriptive text (string) +/** \ref word descriptive text (string) +normal HL mode. +/** \ref w + * normal doxygen HL mode. + */ + + +And final tests for a word: a single char: +=========================================== + +//! \ref word descriptive text (string) +//! \ref w descriptive text (string) + + +//! \image word1 word2 b descriptive text (string) +//! \image a word b descriptive text (string) + + +//! \brief A b c d e description should go on here + + +//! \file word rest of line is normal comment HL +//! \file a word rest of line is normal comment HL + +no doxygen HL mode here. +== END OF TESTFILE == \ No newline at end of file diff --git a/share/tests/hl/highlight.e b/share/tests/hl/highlight.e new file mode 100644 index 0000000..6f07c83 --- /dev/null +++ b/share/tests/hl/highlight.e @@ -0,0 +1,90 @@ +<' + +extend TB_NAME_T : [ ETRC ]; + +extend fifo { + keep soft testbench == ETRC; +}; + +extend ETRC fifo { + + keep direction == POP; + keep soft type == CLASSIC; + + keep PORT_DATAOUT == appendf("esa_data[%d]" , id); + keep PORT_POP_EMPTY == appendf("fifo_empty[%d]", id); + keep PORT_POP_ALMOST_EMPTY == appendf("ESA_PopAE[%d]" , id); + keep PORT_POP_ALMOST_FULL == appendf("ESA_PopAF[%d]" , id); + keep PORT_POP_FULL == ""; + keep PORT_POP_ERROR == ""; + keep PORT_POP_REQ == appendf("etrc_popreq_n[%d]" , id); + keep soft PORT_POP_CLK == "sysclk"; + keep soft PORT_PUSH_CLK == "sysclk"; + +// keep logger.verbosity == HIGH; + + + reset_sig() is { + injector.reset_sig(); + '(PORT_DATAOUT)' = 0; + '(PORT_POP_EMPTY)' = 0; + '(PORT_POP_ALMOST_EMPTY)' = 0; + '(PORT_POP_ALMOST_FULL)' = 0; + '(PORT_POP_REQ)' = 0; + '(PORT_POP_CLK)' = 0; + '(PORT_POP_CLK)' = 1; + }; + + event clkSys is rise('sysclk'); + event bug001 is true('pkdescnt[0]' == 1)@clkSys; + + on bug001 + { + dut_error("Bug 001 found ... crash!"); + }; + +}; + + + +extend ETRC FIFO_INJECTOR { + + pkt_desc_if : pkt_desc_if is instance; + keep pkt_desc_if.MAC_uid == id; + + add_new_pkt_desc() is also { + pkt_desc_if.indicate_one_pck_desc_is_come_in_FIFO(); + }; + + reset_sig() is { + pkt_desc_if.reset_sig(); + }; + +}; + +extend ETRC CLASSIC fifo +{ + + keep ae_seuil == 1; + keep af_seuil == 46; + keep fifo_size == 56; + + + + setState() is also + { + if (fifo_plot &&(sys.time > 200000) && // avoid fifo plot before beginning of operation of RAMC + !((injector.generated_packet_nb == injector.max_generated_packets && injector.stream.size() == 0) + || injector.generated_packet_nb == 0)) + { + if (fifo_use_logger) { + messagef(HIGH, "ETRC[%d] : %d\n", id, fifo.size()); + } + else { + out("__fifo_plot: ", sys.time, " ", fifo.size() ); + }; + }; + }; +}; + +'> diff --git a/share/tests/hl/highlight.erl b/share/tests/hl/highlight.erl new file mode 100644 index 0000000..5b485cb --- /dev/null +++ b/share/tests/hl/highlight.erl @@ -0,0 +1,68 @@ +% testing for the erlang syntax highlighter +% NOTE alerts work in comments to TODO ! + +% pragmas (show as keywords) +-module +-export +-define +-undef +-ifdef +-ifndef +-else +-endif +-include +-include_lib + +% key words +after begin case catch cond end fun if let of query receive all_true some_true + +% operators +div rem or xor bor bxor bsl bsr and band not bnot ++ - * / == /= =:= =/= < =< > >= ++ -- = ! <- + +% separators (show as functions) +( ) { } [ ] . : | || ; , ? -> # + +% functions - predefined (part of erlang module) - show as functions +abs accept alarm apply atom_to_list binary_to_list binary_to_term check_process_code +concat_binary date delete_module disconnect_node element erase exit float float_to_list +garbage_collect get get_keys group_leader halt hd integer_to_list is_alive is_atom is_binary +is_boolean is_float is_function is_integer is_list is_number is_pid is_port is_process_alive +is_record is_reference is_tuple length link list_to_atom list_to_binary list_to_float list_to_integer +list_to_pid list_to_tuple load_module loaded localtime make_ref module_loaded node nodes now +open_port pid_to_list port_close port_command port_connect port_control ports pre_loaded process_flag +process_info processes purge_module put register registered round self setelement size +spawn spawn_link spawn_opt split_binary statistics term_to_binary throw time tl trunc tuple_to_list +unlink unregister whereis + +% functions - inferred +module:function +function() + +% atoms (show as "char") +% begin with underscore, lowercase, contain numbers letters and @ - or anything between '' +middle_underscore +abc ab4d a@cd8 a@ +'And this is (\012) an atom \' Atoo' Variable 'atom again' + +% variables (begin with capital letter or underscore, contain numbers, letters and @) +_leadingUnderscore AbdD@ B45@c + +% this is a string +"a string sits between \" double quotes" atom "more string" + +% integers (decimal) +1. 234 $A + +% integers (specified base) +2#10101 34#567 + +% float +12.23 12.9e-67 12.8E+89 33.34e89 + +% and finally some real code, so we can see what it looks like... +-module(codetest). % everything is in a module +-export([fac/1]). % name and number of arguments - need this to be called outside of the module + +fac(N) when N > 0 -> N * fac(N-1); +fac(N) when N == 0 -> 1. diff --git a/share/tests/hl/highlight.exu b/share/tests/hl/highlight.exu new file mode 100644 index 0000000..3651adf --- /dev/null +++ b/share/tests/hl/highlight.exu @@ -0,0 +1,97 @@ +-- Test file for Kate's Euphoria syntax highlighting/code folding. +-- BEGIN region marker test + +-- code here + +-- END region marker test + +-- The N Queens Problem: +-- Place N Queens on an NxN chess board +-- such that they don't threaten each other. +constant N = 8 -- try some other sizes +constant ROW = 1, COLUMN = 2 +constant TRUE = 1, FALSE = 0 +type square(sequence x) +-- a square on the board + return length(x) = 2 +end type +type row(integer x) +-- a row on the board + return x >= 1 and x <= N +end type + +function threat(square q1, square q2) +-- do two queens threaten each other? + if q1[COLUMN] = q2[COLUMN] then + return TRUE + elsif q1[ROW] - q1[COLUMN] = q2[ROW] - q2[COLUMN] then + return TRUE + elsif q1[ROW] + q1[COLUMN] = q2[ROW] + q2[COLUMN] then + return TRUE + elsif q1[ROW] = q2[ROW] then + return TRUE + else + return FALSE + end if +end function + +function conflict(square q, sequence queens) +-- Would square p cause a conflict with other queens on board so far? + for i = 1 to length(queens) do + if threat(q, queens[i]) then + return TRUE + end if + end for + return FALSE +end function + +integer soln +soln = 0 -- solution number + +procedure print_board(sequence queens) +-- print a solution, showing the Queens on the board + integer k + position(1, 1) + printf(1, "Solution #%d\n\n ", soln) + for c = 'a' to 'a' + N - 1 do + printf(1, "%2s", c) + end for + puts(1, "\n") + for r = 1 to N do + printf(1, "%2d ", r) + for c = 1 to N do + if find({r,c}, queens) then + puts(1, "Q ") + else + puts(1, ". ") + end if + end for + puts(1, "\n") + end for + puts(1, "\nPress Enter. (q to quit) ") + while TRUE do + k = get_key() + if k = 'q' then + abort(0) + elsif k != -1 then + exit + end if + end while +end procedure + +procedure place_queen(sequence queens) +-- place queens on a NxN chess board +-- (recursive procedure) + row r -- only need to consider one row for each queen + if length(queens) = N then + soln += 1 + print_board(queens) + return + end if + r = length(queens)+1 + for c = 1 to N do + if not conflict({r,c}, queens) then + place_queen(append(queens, {r,c})) + end if + end for +end procedure diff --git a/share/tests/hl/highlight.f90 b/share/tests/hl/highlight.f90 new file mode 100644 index 0000000..e2008c2 --- /dev/null +++ b/share/tests/hl/highlight.f90 @@ -0,0 +1,181 @@ +! This file is an example to test the syntax highlighting file F.xml +! (for fortran 90 and F) + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! THIS IS AN EXAMPLE OF A MODULE ! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +module module_example + + ! use 'implicit none' when you want all variables to be declared + implicit none + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! PUBLICS AND PRIVATES + + ! In fortran 90 you can define your own operator + public :: operator(.norm.) + public :: operator(+) ! <-- you can also overload the usual operators + public :: factorial + public :: example_fn + + private :: point3d_add + private :: point3d_norm + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! USER-DEFINED TYPES... + + ! This is a definition to use in declarations of real variables, + ! parameters, etc. + integer, parameter, public :: kr = selected_real_kind(10) + + ! This is a user-defined type + type, public :: point3d + real(kind=kr) :: x, y, z + end type point3d + + ! This type is useless: it is only an example of type definition! + type, public :: example_type + complex(kind=kr) :: c ! <-- a complex number (two reals of kind kr)! + real, dimension(-10:10) :: & ! <-- this line does not end here! + r1, r2 ! <-- this is the final part of the previous line + real, pointer, dimension(:) :: pointer_to_array_of_real + real, dimension(:), pointer :: array_of_pointer_to_real + end type example_type + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! INTERFACES... + + ! Interface for the norm of a 3-D vector + interface operator(.norm.) + module procedure point3d_norm + end interface + + ! Interface for the operator '+' + interface operator(+) + module procedure point3d_add + end interface + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! SOME DECLARATIONS... + + ! A real number can be declared with the following line: + real(kind=kr) :: real_var1 + ! But if you are not interested on the precision of floating point numbers, + ! you can use simply: + real :: real_var2 + + ! An array can be declared in two ways: + real(kind=kr), dimension(1:10, -4:5), private :: a, b, c + real(kind=kr), private :: d(1:10, -4:5) + + ! This is a string with fixed lenght + character(len=10) :: str_var + + ! This is an allocatable array, which can be a target of a pointer + type(example_type), private, dimension(:), allocatable, target :: & + many_examples + +! Fortran 90 hasn't got its own preprocessor, it uses the C preprocessor! +#ifdef XXX +c <-- this is a comment in the old fortran 77 style (fixed form) +c This is a free form file, so we shouldn't use this kind of comments! +c But fortran 90 still understands fixed form, when parsing sources with +c the *.f extension. + c ! <-- this 'c' shouldn't be highlighted as a comment! +#endif + +contains + + + ! The sum of two points + pure function point3d_add(a, b) result(rs) + type(point3d) :: rs + type(point3d), intent(in) :: a, b + rs%x = a%x + b%x + rs%y = a%y + b%y + rs%z = a%z + b%z + end function point3d_add + + + ! The norm of a point + pure function point3d_norm(a) result(rs) + real(kind=kr) :: rs + type(point3d), intent(in) :: a + rs = sqrt(a%x * a%x + a%y * a%y + a%z * a%z) + end function point3d_norm + + + ! A simple recursive function + recursive function factorial(i) result (rs) + integer :: rs + integer, intent(in) :: i + if ( i <= 1 ) then + rs = 1 + else + rs = i * factorial(i - 1) + end if + end function factorial + + + ! This is a useless function + subroutine example_fn(int_arg, real_arg, str_arg) + integer, intent(in) :: int_arg + real(kind=kr), intent(out) :: real_arg + character(len=*), intent(in) :: str_arg + + type(example_type), pointer :: p + integer :: n, i, j + logical :: flag + + flag = .true. ! .true. is not an operator! + if ( flag .and. flag ) then ! .and. is a pre-defined operator + print *, "blabla" + end if + + ! Examples of inquiry functions: allocated, lbound, ubound. + if ( .not. allocated(many_examples) ) then + allocate( many_examples(10) ) + end if + print *, "Lower bound = ", lbound(many_examples, 1) + print *, "Upper bound = ", ubound(many_examples, 1) + + p => many_examples(5) ! <-- p is a pointer + + ! A strange way to calculate i*i: add the first i odd numbers + i = 6 + j = 0 + do n = 1, i + j = j + (2*n - 1) + end do + print *, "i*i = ", i*i, j + + real_arg = real(j) ! <-- here the highlighting is not very good: + ! it is unable to distinguish between this and a definition like: + ! real(kind=kr) :: a + deallocate( many_examples ) + end subroutine example_fn + +end module module_example + + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +! THIS IS THE MAIN PROGRAM ! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +program example + use module_example + + ! this is another example of use of the 'implicit' keyword + implicit double precision (a-h,o-z) + + real(kind=kr) :: var_out + + type(point3d) :: & + a = point3d(0.0_kr, 1.0_kr, 2.0_kr), & + b = point3d(4.0_kr, 5.0_kr, 6.0_kr) + + print *, "a + b = ", .norm. (a + b) + print *, "factorial of 5 = ", factorial(5) + + call example_fn(1, var_out, "hello!") + +end program example diff --git a/share/tests/hl/highlight.fs b/share/tests/hl/highlight.fs new file mode 100644 index 0000000..f4bf658 --- /dev/null +++ b/share/tests/hl/highlight.fs @@ -0,0 +1,24 @@ +(* Fibonacci Number formula from Wikipedia's F# article *) +let rec fib n = + match n with + | 0 | 1 -> n + | _ -> fib (n - 1) + fib (n - 2) + +(* An alternative approach - a lazy recursive sequence of Fibonacci numbers *) +let rec fibs = Seq.cache <| seq { yield! [1; 1] + for x, y in Seq.zip fibs <| Seq.skip 1 fibs -> x + y } + +(* Another approach - a lazy infinite sequence of Fibonacci numbers *) +let fibSeq = Seq.unfold (fun (a,b) -> Some(a+b, (b, a+b))) (1,1) + +(* Print even fibs *) +[1 .. 10] +|> List.map fib +|> List.filter (fun n -> (n % 2) = 0) +|> printlist + +(* Same thing, using sequence expressions *) +[ for i in 1..10 do + let r = fib i + if r % 2 = 0 then yield r ] +|> printlist diff --git a/share/tests/hl/highlight.glsl b/share/tests/hl/highlight.glsl new file mode 100644 index 0000000..3495757 --- /dev/null +++ b/share/tests/hl/highlight.glsl @@ -0,0 +1,62 @@ +// This is a test file for the Katepart GLSL Syntax Highlighting. + +normal text +// this is a single-line comment +normal text +/* this +is a multi-line +comment */ +normal text + +some_symbol.some_member; +some_symbol.some_member_function(); +some_function(); + +// this is a function +void main() +{ + float f = 1.4e3; // decimal float literal + int i1 = 2884; // decimal int literal + int i2 = 0x44; // hex int literal + int i3 = 0456; // octal int literal +} + +// this is a structure +struct some_struct +{ + vec3 some_member_vector; +}; + +# this is +#preprocessor code + +// all keywords +break continue do for while +if else +true false +discard return +struct + +// all basic types +float int void bool +mat2 mat3 mat4 +vec2 vec3 vec4 +ivec2 ivec3 ivec4 +bvec2 bvec3 bvec4 +sampler1D sampler2D sampler3D +samplerCube sampler1DShadow sampler1DShadow + +// all type qualifiers +attribute const uniform varying +in out inout + +// attensions: +// FIXME +// TODO +// BUG + +// some of the std functions +radians degrees sin cos tan asin acos atan + +// some of the std variables +gl_Position gl_PointSize gl_ClipVertex diff --git a/share/tests/hl/highlight.hs b/share/tests/hl/highlight.hs new file mode 100644 index 0000000..057a3f3 --- /dev/null +++ b/share/tests/hl/highlight.hs @@ -0,0 +1,124 @@ +-- test file for Haskell syntax highlighting in KDE's Kate + +-- The test file for literate Haskell can be easily created like this: +-- cat highlight.hs | sed -e "s|^|> |" -e "s|> -- ||" -e "s|^> $||" > highlight.lhs +-- You only have to manually edit the multi-line comment below. + +-- this is a single-line comment + +{- this is a multi-line comment + +Things like "a string" or a 'c' character shouldn't be highlighted in here. + +-- I could even start a new +-- one-line comment. + +-} + +-- a data definition + +data Tree a = Br (Tree a) (Tree a) | Leaf a | Nil deriving (Show, Eq) + + +-- function definition, "funnyfunction::", "Integer", "Int", "Bool" should be highlighted + +funnyfunction::(Tree a)=>[a]->Integer->Int->Bool + + +-- strings and chars +-- first line of function definitions (type declaration) should be highlighted + +strangefunction::Int->String +strangefunction 1 = "hello" +strangefunction 2 = "what's up" +strangefunction 3 = (strangefunction 1) ++ ", " ++ (strangefunction 2) +strangefunction 4 = 'a':'b':'c':'"':[] -- will return "abc" +strangefunction 5 = '\n':[] +strangefunction 6 = '\invalidhaskell':[] + +-- function name including the single quote character +-- and infix operator (`div`) + +justtesting'::Int->Int +justtesting' 2 = 2+1 +justtesting' 9 = 7 `div` 2 + +-- same definition as above, slightly different function name and a couple more whitespaces + +justtesting'' :: Int -> Int +justtesting'' 2 = 3 +justtesting'' 9 = 3 + 9 - 9 + +-- the following lines are copied out of Haskell's "Prelude.hs" + +infixl 7 *, /, `quot`, `rem`, `div`, `mod`, :%, % + + +-- everything highlighted except the "a" + +class Bounded a where + minBound, maxBound :: a + +class (Num a, Ord a) => Real a where + toRational :: a -> Rational + +-- finally, some keyword lists + +-- keywords + +case, class, data, deriving, do, else, if, in, infixl, infixr, instance, let, module, of, primitive, +then, type, where + +-- infix operators + +quot, rem, div, mod, elem, notElem, seq + +-- this stuff is not handled yet + +!!, %, &&, $!, $, *, **, -,., /=, <, <=, =<<, ==, >, >=, >>, >>=, ^, ^^, ++, || + +-- functions + +FilePath, IOError, abs, acos, acosh, all, and, any, appendFile, +approxRational, asTypeOf, asin, asinh, atan, atan2, atanh, basicIORun, +break, catch, ceiling, chr, compare, concat, concatMap, const, cos, cosh, +curry, cycle, decodeFloat, denominator, digitToInt, div, divMod, drop, +dropWhile, either, elem, encodeFloat, enumFrom, enumFromThen, +enumFromThenTo, enumFromTo, error, even, exp, exponent, fail, filter, flip, +floatDigits, floatRadix, floatRange, floor, fmap, foldl, foldl1, foldr, +foldr1, fromDouble, fromEnum, fromInt, fromInteger, fromIntegral, +fromRational, fst, gcd, getChar, getContents, getLine, head, id, inRange, +index, init, intToDigit, interact, ioError, isAlpha, isAlphaNum, isAscii, +isControl, isDenormalized, isDigit, isHexDigit, isIEEE, isInfinite, isLower, +isNaN, isNegativeZero, isOctDigit, isPrint, isSpace, isUpper, iterate, last, +lcm, length, lex, lexDigits, lexLitChar, lines, log, logBase, lookup, map, +mapM, mapM_, max, maxBound, maximum, maybe, min, minBound, minimum, mod, +negate, not, notElem, null, numerator, odd, or, ord, otherwise, pi, pred, +primExitWith, print, product, properFraction, putChar, putStr, putStrLn, +quot, quotRem, range, rangeSize, read, readDec, readFile, readFloat, +readHex, readIO, readInt, readList, readLitChar, readLn, readOct, readParen, +readSigned, reads, readsPrec, realToFrac, recip, rem, repeat, replicate, +return, reverse, round, scaleFloat, scanl, scanl1, scanr, scanr1, seq, +sequence, sequence_, show, showChar, showInt, showList, showLitChar, +showParen, showSigned, showString, shows, showsPrec, significand, signum, +sin, sinh, snd, span, splitAt, sqrt, subtract, succ, sum, tail, take, +either, elem, encodeFloat, enumFrom, enumFromThen, enumFromThenTo, +enumFromTo, error, even, exp, exponent, fail, filter, flip, floatDigits, +floatRadix, floatRange, floor, fmap, takeWhile, tan, tanh, threadToIOResult, +toEnum, toInt, toInteger, toLower, toRational, toUpper, truncate, uncurry, +undefined, unlines, until, unwords, unzip, unzip3, userError, words, +writeFile, zip, zip3, zipWith, zipWith3 + +-- type constructors + +Bool, Char, Double, Either, Float, IO, Integer, Int, Maybe, Ordering, Rational, Ratio, ReadS, +ShowS, String + +-- classes + +Bounded, Enum, Eq, Floating, Fractional, Functor, Integral, Ix, Monad, Num, Ord, Read, RealFloat, +RealFrac, Real, Show + +-- data constructors + +EQ, False, GT, Just, LT, Left, Nothing, Right, True diff --git a/share/tests/hl/highlight.jsp b/share/tests/hl/highlight.jsp new file mode 100644 index 0000000..d912836 --- /dev/null +++ b/share/tests/hl/highlight.jsp @@ -0,0 +1,170 @@ +<%-- + This page won't actually work, as it is simply designed to display jsp syntax highlighting. +--%> +<%@ page info="A Page to Test Kate Jsp Syntax Highlighting" language="java" errorPage="/test-error-page.jsp"%> +<%@ include file="/include/myglobalvars.jsp"%> --%> +<%@ page import="java.util.*, + java.io.*, + java.math.*" %> +<%@ taglib uri="/WEB-INF/lib/si_taglib.tld" prefix="si"%> + + +<% + // We can decipher our expected parameters here. + String parm1 = noNull(request.getParameter(PARAMETER_1)).trim(); + String parm2 = noNull(request.getParameter(PARAMETER_2)).trim(); + String parm3 = noNull(request.getParameter(PARAMETER_3)).trim(); + String parm4 = noNull(request.getParameter(PARAMETER_4)).trim(); + String parm5 = noNull(request.getParameter(PARAMETER_5)).trim(); + + // A sample collection of Integers to display some code folding. + List intList = getIntList(10); + + +%> + + A Sample Jsp + + + + + <%-- The top label table. --%> + + + + +
The following parameters were detected:
+ + <%-- Display the parameters which might have been passed in. --%> + + <%-- Label; Actual Parameter String; Value Detected --%> + + + + + + + <%-- Label; Actual Parameter String; Value Detected --%> + + + + + + + <%-- Label; Actual Parameter String; Value Detected --%> + + + + + + + <%-- Label; Actual Parameter String; Value Detected --%> + + + + + + + <%-- Label; Actual Parameter String; Value Detected --%> + + + + + +
PARAMETER_1<%=PARAMETER_1%>"<%=parm1%>"
PARAMETER_2<%=PARAMETER_2%>"<%=parm2%>"
PARAMETER_3<%=PARAMETER_3%>"<%=parm3%>"
PARAMETER_4<%=PARAMETER_4%>"<%=parm4%>"
PARAMETER_5<%=PARAMETER_5%>"<%=parm5%>"
+ +

+ + <%-- Display our list of random Integers (shows code folding). --%> + +<% + if (intList != null && intList.size() > 0) { +%> + +<% + Iterator intListIt = intList.iterator(); + while (intListIt.hasNext()) { + Integer i = (Integer) intListIt.next(); +%> + +<% + } + } else { +%> + +<% + } +%> +
Here are the elements of intList...
<%=i.toString()%>
Oooops, we forgot to initialize intList!
+ +

+ + <%-- We can call javascript functions. --%> + + + + + + +
Test our javascript...
+ +

+ <%-- If we actually had defined a tag library. --%> + + +
+ + + + +
+ +

+ <%-- Expression language. --%> + + + + + + +
myParam's value: ""
+ + +<%! + /* A place for class variables and functions... */ + + // Define some sample parameter names that this page might understand. + private static final String PARAMETER_1 = "p1"; + private static final String PARAMETER_2 = "p2"; + private static final String PARAMETER_3 = "p3"; + private static final String PARAMETER_4 = "p4"; + private static final String PARAMETER_5 = "p5"; + + // Returns str trimmed, or an empty string if str is null. + private static String noNull(String str) { + String retStr; + if (str == null) + retStr = ""; + else + retStr = str.trim(); + + return retStr; + } + + // Returns a list of Integers with listSize elements. + private static List getIntList(int listSize) { + ArrayList retList = new ArrayList(listSize); + for (int i = 0; i < listSize; i++) + retList.add(new Integer( (int) (Math.random() * 100) )); + + return retList; + } +%> \ No newline at end of file diff --git a/share/tests/hl/highlight.ld b/share/tests/hl/highlight.ld new file mode 100644 index 0000000..967c0e2 --- /dev/null +++ b/share/tests/hl/highlight.ld @@ -0,0 +1,28 @@ +/* Example GNU LD Linker Script */ +ENTRY(main) +OUTPUT_FORMAT(elf32-i386) + +TEXT_VADDR = 0x00100000; +DATA_VADDR = 32M; +BSS_VADDR = 128M; + +SECTIONS { + . = TEXT_VADDR; + .text ALIGN(PAGE_SIZE) : { + *(.text) + } + . = DATA_VADDR; + .data ALIGN(PAGE_SIZE) : { + *(.data) + *(.rodata) + } + . = BSS_VADDR; + .bss ALIGN(PAGE_SIZE) : { + *(.bss) + *(COMMON) + } + /DISCARD/ : { + *(.comment) + } +} + diff --git a/share/tests/hl/highlight.lex b/share/tests/hl/highlight.lex new file mode 100644 index 0000000..33527bd --- /dev/null +++ b/share/tests/hl/highlight.lex @@ -0,0 +1,82 @@ +/* This test file tests kates Lex/Flex highlighting */ + +%option c++ +%option yyclass="KateTester" +%option yylineno + + /* This is a C(++) comment */ + +/* This one is a lex comment ! */ + +%{ +#include +#include "realparser.hpp" +using namespace std; +%} + +/* Some definitions */ +DIGIT [0-9] +LETTER [_a-zA-Z] + +%% + + /* Comment *shall be indented here* */ +[ \t\n\r]+ + + /* Note: there is a bad } just here vvv */ +\/\*([^\*]|\*[^/])*\*\/ { foo(a, b, c); } } + + /* A start condition scope... */ +{ + "a" { + + /* C mode ! */ + return 0; +} + + "b" %{ + + /* C mode, too ! */ + return 0; +%} + + "c" return 0; // C++ comment +} + + /* Big rule */ +\"([^"\\]|\\.)*\" { + + yylval.string_val = new char[strlen(yytext) + 1]; + int j = 0, i = 1; + + while (yytext[i] != '"') + if (yytext[i] != '\\') + yylval.string_val[j++] = yytext[i++]; + else + switch (yytext[i + 1]) + { + case 'n': + yylval.string_val[j++] = '\n'; i += 2; + break; + default: + yylval.string_val[j++] << yytext[i + 1], i += 2; + } + + yylval.string_val[j] = 0; + return TOK_STRING; + +} + + /* Dot (match all) */ +. {return yylval.int_val = yytext[0];} + +%% + +// Here is pure C(++) +#include + +int main(void) +{ + std::cout << "Hello, World\n"; + return 0; +} diff --git a/share/tests/hl/highlight.lhs b/share/tests/hl/highlight.lhs new file mode 100644 index 0000000..9dc52e5 --- /dev/null +++ b/share/tests/hl/highlight.lhs @@ -0,0 +1,124 @@ +test file for Haskell syntax highlighting in KDE's Kate + +The test file for literate Haskell can be easily created like this: + cat highlight.hs | sed -e "s|^|> |" -e "s|> -- ||" -e "s|^> $||" > highlight.lhs +You only have to manually edit the multi-line comment below. + +this is a single-line comment + +{- this is a multi-line comment + +Things like "a string" or a 'c' character shouldn't be highlighted in here. + +I could even start a new +one-line comment. + +-} + +a data definition + +> data Tree a = Br (Tree a) (Tree a) | Leaf a | Nil deriving (Show, Eq) + + +function definition, "funnyfunction::", "Integer", "Int", "Bool" should be highlighted + +> funnyfunction::(Tree a)=>[a]->Integer->Int->Bool + + +strings and chars +first line of function definitions (type declaration) should be highlighted + +> strangefunction::Int->String +> strangefunction 1 = "hello" +> strangefunction 2 = "what's up" +> strangefunction 3 = (strangefunction 1) ++ ", " ++ (strangefunction 2) +> strangefunction 4 = 'a':'b':'c':'"':[] -- will return "abc" +> strangefunction 5 = '\n':[] +> strangefunction 6 = '\invalidhaskell':[] + +function name including the single quote character +and infix operator (`div`) + +> justtesting'::Int->Int +> justtesting' 2 = 2+1 +> justtesting' 9 = 7 `div` 2 + +same definition as above, slightly different function name and a couple more whitespaces + +> justtesting'' :: Int -> Int +> justtesting'' 2 = 3 +> justtesting'' 9 = 3 + 9 - 9 + +the following lines are copied out of Haskell's "Prelude.hs" + +> infixl 7 *, /, `quot`, `rem`, `div`, `mod`, :%, % + + +everything highlighted except the "a" + +> class Bounded a where +> minBound, maxBound :: a + +> class (Num a, Ord a) => Real a where +> toRational :: a -> Rational + +finally, some keyword lists + +keywords + +> case, class, data, deriving, do, else, if, in, infixl, infixr, instance, let, module, of, primitive, +> then, type, where + +infix operators + +> quot, rem, div, mod, elem, notElem, seq + +this stuff is not handled yet + +> !!, %, &&, $!, $, *, **, -,., /=, <, <=, =<<, ==, >, >=, >>, >>=, ^, ^^, ++, || + +functions + +> FilePath, IOError, abs, acos, acosh, all, and, any, appendFile, +> approxRational, asTypeOf, asin, asinh, atan, atan2, atanh, basicIORun, +> break, catch, ceiling, chr, compare, concat, concatMap, const, cos, cosh, +> curry, cycle, decodeFloat, denominator, digitToInt, div, divMod, drop, +> dropWhile, either, elem, encodeFloat, enumFrom, enumFromThen, +> enumFromThenTo, enumFromTo, error, even, exp, exponent, fail, filter, flip, +> floatDigits, floatRadix, floatRange, floor, fmap, foldl, foldl1, foldr, +> foldr1, fromDouble, fromEnum, fromInt, fromInteger, fromIntegral, +> fromRational, fst, gcd, getChar, getContents, getLine, head, id, inRange, +> index, init, intToDigit, interact, ioError, isAlpha, isAlphaNum, isAscii, +> isControl, isDenormalized, isDigit, isHexDigit, isIEEE, isInfinite, isLower, +> isNaN, isNegativeZero, isOctDigit, isPrint, isSpace, isUpper, iterate, last, +> lcm, length, lex, lexDigits, lexLitChar, lines, log, logBase, lookup, map, +> mapM, mapM_, max, maxBound, maximum, maybe, min, minBound, minimum, mod, +> negate, not, notElem, null, numerator, odd, or, ord, otherwise, pi, pred, +> primExitWith, print, product, properFraction, putChar, putStr, putStrLn, +> quot, quotRem, range, rangeSize, read, readDec, readFile, readFloat, +> readHex, readIO, readInt, readList, readLitChar, readLn, readOct, readParen, +> readSigned, reads, readsPrec, realToFrac, recip, rem, repeat, replicate, +> return, reverse, round, scaleFloat, scanl, scanl1, scanr, scanr1, seq, +> sequence, sequence_, show, showChar, showInt, showList, showLitChar, +> showParen, showSigned, showString, shows, showsPrec, significand, signum, +> sin, sinh, snd, span, splitAt, sqrt, subtract, succ, sum, tail, take, +> either, elem, encodeFloat, enumFrom, enumFromThen, enumFromThenTo, +> enumFromTo, error, even, exp, exponent, fail, filter, flip, floatDigits, +> floatRadix, floatRange, floor, fmap, takeWhile, tan, tanh, threadToIOResult, +> toEnum, toInt, toInteger, toLower, toRational, toUpper, truncate, uncurry, +> undefined, unlines, until, unwords, unzip, unzip3, userError, words, +> writeFile, zip, zip3, zipWith, zipWith3 + +type constructors + +> Bool, Char, Double, Either, Float, IO, Integer, Int, Maybe, Ordering, Rational, Ratio, ReadS, +> ShowS, String + +classes + +> Bounded, Enum, Eq, Floating, Fractional, Functor, Integral, Ix, Monad, Num, Ord, Read, RealFloat, +> RealFrac, Real, Show + +data constructors + +> EQ, False, GT, Just, LT, Left, Nothing, Right, True diff --git a/share/tests/hl/highlight.lisp b/share/tests/hl/highlight.lisp new file mode 100644 index 0000000..e86c85f --- /dev/null +++ b/share/tests/hl/highlight.lisp @@ -0,0 +1,36 @@ +;; This test file tests kates common lisp highlighting +#| +multilinecomment :) +|# + +;BEGIN region marker + +;END end + +(defun bin-search (obj vec) + (let ((len (length vec))) + (and (not (zerop len)) + (finder obj vec 0 (- len 1))))) + +(defun parse-date (str) + (let ((toks (tokens str #'constituent 0))) + (list (parse-integer (first toks)) + (parse-month (second toks)) + (parse-integer (third toks))))) + +(defconstant month-names + #("jan" "feb" "mar" "apr" "may" "jun" + "jul" "aug" "sep" "oct" "nov" "dec")) + +(defstruct buf + vec (start -1) (used -1) (new -1) (end -1)) + +(defparameter *words* (make-hash-table :size 10000)) + +(defmacro while (test &rest body) + `(do () + ((not ,test)) + ,@body)) + +(define-modify-macro append1f (val) + (lambda (lst val) (append lst (list val)))) diff --git a/share/tests/hl/highlight.ly b/share/tests/hl/highlight.ly new file mode 100644 index 0000000..29aa7a6 --- /dev/null +++ b/share/tests/hl/highlight.ly @@ -0,0 +1,114 @@ +% This is a file to test the Lilypond highlighting features of Katepart. +% This is NOT a valid lilypond file, because it also shows the +% highlighting of some invalid lilypond constructs! +% This is a line comment. + +%{ +this is a block comment, that can occur inside a line, or across +multiple lines. +%} + +\header { + title = "Katepart Lilypond syntax highlighting test file" + composer = %{"Wilbert Berendsen"%} "Anonymus" + poet = "The KDE team" + opus = "1" + copyright = "Share and enjoy!" +} + +\paper { + #(set-paper-size "a4") % a hash introduces scheme + indent = 0 % recognize variable names inside \paper, \layout etc. + between-system-space = 3\mm +} + +\layout { + \context { + \Score + \remove Bar_number_engraver % recognize engraver names + \remove "Bar_number_engraver" % also when quoted! + } +} + +% { and << block are folded +\score { + \new StaffGroup << + \new ChordNames \chordmode { c2sus4/f g2/d c1 } + \new Staff \new Voice ="mel" { + \key f \major + \time 4/4 + \partial 4 + \set Staff.instrumentName = "Bla." + \once \override Staff.NoteHead #'color = #red + % dynamics, articulations and markup + c8\p d\< e-. f-> g a\f c-5\markup {Hoi} + \notemode { c d e f } + \repeat volta 2 { + % complex durations are highlighted: + g4*2/3 + } + \times 2/3 {e8 f g} + % there is some error checking: + % often made mistake to have octavemarks after the duration: + c2' + % invalid durations are caught: + g3 + } + \context Lyrics \lyricsto "mel" { + \set fontSize = #1 + this is a line of ly -- rics. + with4 dur -- a -- tions.2. + % errors like forgetting spaces are found: + space-- flight %{i.s.o.%} space -- flight + space at end for -- got -- ten as well.} + + \new DrumStaff \drummode { hihat4 bassdrum8 } + \new FiguredBass \figuremode { + <5 4>8 <6-> + } + >> + \midi { + \context { + \Score + tempoWholesPerMinute = #(ly:make-moment 60 2) + } + } +} + +av = #(define-music-function (parser location voice) +(string?) +; scheme comments are recognized in scheme +; Lilypond inside scheme works as well: +#{ + \set associatedVoice = $voice +#}) + + + + +% inside scheme some elements are highlighted: +#(define (naturalise-pitch p) + (let* ((o (ly:pitch-octave p)) + (a (* 4 (ly:pitch-alteration p))) + (n (ly:pitch-notename p))) + (bla 'ArticulationEvent 'ChoirStaff) + (cond + ((> a 2) (set! a (- a 4)) (set! n (+ n 1))) + ((< a -2) (set! a (+ a 4)) (set! n (- n 1)))) + + (if (< n 0) (begin (set! o (- o 1)) (set! n (+ n 7)))) + (if (> n 6) (begin (set! o (+ o 1)) (set! n (- n 7)))) + + (ly:make-pitch o n (/ a 4)))) + +% markup is also highlighted +\markup { + \line { + text test Voice Staff % note Lilypond keywords are not highlighted here + } + \score { \relative c' { 2( d) } } + \italic bla + \override #'(baseline-skip . 2) { + \underline blu + } +} diff --git a/share/tests/hl/highlight.m b/share/tests/hl/highlight.m new file mode 100644 index 0000000..f240138 --- /dev/null +++ b/share/tests/hl/highlight.m @@ -0,0 +1,61 @@ +%%===================================================== +% MATLAB test code for Kate/Kwrite syntax highlighting +% kate: hl Matlab +%%===================================================== + +% Numbers _____________________________________________ +5, 5.5, .1, 0.1, 0.4e5, 1.2e-5, 5i, 5.3i, 6j, .345+3i +5', 5.5', .1', 0.1', 0.4e5', 1.2e-5', 5i', 5.3i', 6j', .345+3i' + +% Operators ___________________________________________ +% relational operators +'asdf'~=4, c<=4, d>=4, ab, a==b, b||c, b&&c +% elementwise arithmetic operators +a.^b, a.*b a./b, 1:4:5 +% single-character binary arithmetic +a+3, a-3, a*2, a^3, a/3, a\3, a|b, a&b +% unary operators +a = ~g; g = @sfdgdsf(sdfsd,345); g.' + 1i.' - ('asdf').' +% separators and delimiter +(asd),[sadf];{asdf},;;,;;;() +% continuation +a = 1+ ... + 2; + +% Strings and adjoint _________________________________ +% incomplete strings +'string +'str'' +'str''ing +% complete strings +'string' % simple string +'''' % string containing ' +'str''ing' % one string containing ' +'string' 'string' % two strings +'asdf' 'asdf''' variable % two strings and a variable +'asdf''asdf'' fsgdfg' + (asdf)' - 'asdf'.' + []''''.';'' +'sadf'.' % string transpose +% adjoint +{'asdf'}' + 1 +('asdf')' + 1 +['asdf']' + 1 +'' var''' % empty string, var with >1 adjoints +[5]'*{5}'*('asd')'.'+(5)'*6'*asdf'*asdf'.' % many adjoints +A'*B + 1 % adjoint +A.'*B + 1 % transpose +A.'.'*B + 1 % double transpose +A'.' + 1 % adjoint, then transpose +A.'' % transpose, then adjoint + +% System command ______________________________________ +!hostname +!cp * /tmp + +% Reserved keywords ___________________________________ +function, persistent, global +switch, case, otherwise +if, else, elseif +try, catch +for, while, break, continue +end, return +function, FUNCTION, Function % case sensitive! \ No newline at end of file diff --git a/share/tests/hl/highlight.mac b/share/tests/hl/highlight.mac new file mode 100644 index 0000000..7db47b5 --- /dev/null +++ b/share/tests/hl/highlight.mac @@ -0,0 +1,1828 @@ +/* +------------------------------------------------------------------------ +Efficient Galois Fields in Maxima + +by Alasdair McAndrew +and later extended by Fabrizio Caruso and Jacopo Daurizio + +it is distribuited together with gf_roots by Jacopo Daurizio + +Authors: + +Fabrizio Caruso (optimizations, testing) +Jacopo D'Aurizio (optimizations, modular roots) +Alasdair McAndrew (original version of the package, pohlig-helman log, etc... ) +------------------------------------------------------------------------*/ + +/* Released under terms of the GNU General Public License, version 2, + * by permission of the authors to Robert Dodier circa 2007-12-02. + */ + +/* Defines a flag for dealing with large fields. If it is set to "false", +then lookup tables are used for exponentiation and logarithms. Otherwise +other algorithms are used */ + +define_variable(largefield,true,bool)$ +define_variable(gf_char,0,integer)$ +define_variable(gf_exp,0,integer)$ +define_variable(gf_order,0,integer)$ +define_variable (gf_one, 'gf_one, any_check)$ +define_variable (gf_prim, 'gf_prim, any_check)$ +define_variable (gf_irr, 'gf_irr, any_check)$ +define_variable (gf_list, 'gf_list, any_check)$ +define_variable (gen_powers, 'gf_list, any_check)$ +remvalue(x,z,gf_char,gf_exp,gf_irr,pg,gp,lg,gf_prim,gf_one,gf_order,gf_list,gen_powers)$ + + +/* --------------------------------------------------------------------------------------------- */ +/* Settings */ + +GF_VERBOSE:false; /* Verbosity */ +GF_WARNING: true; /* Warnings */ +GF_IRREDUCIBILITY_CHECK:false; /* Irreducibility test for the minimal polynomial of the extension */ + +/* +------------------------------------------------------------------------------------------------ */ + + +/* It defines a new current field with gf_char=b, min. pol.= p of deg= e*/ +gf_set([ars]):=block([gj,m,i,j,dg], + if length(ars)=1 then + ( + gf_setp(ars[1]), + return(true) + ) + else + ( + if length(ars)=2 then + ( + if numberp(ars[2]) then + ( + if ars[2]=0 and GF_WARNING then + ( + print("WARNING: the irreducible is zero! We assume GF(",ars[1],")"), + gf_setp(ars[1]), + return(true) + ) + else + ( + error("ERROR: you tried to extend with a non-zero constant!"), + return(false) + ) + ) + else + ( + dg:hipow(ars[2],x), + + if dg=1 then + gf_setp(ars[1]), + gf_irr:ars[2], + gf_exp:dg, + return(true) + ) + ) + else + ( + gf_exp:ars[2], + if gf_exp=1 then + ( + gf_setp(ars[1]), + gf_irr:rat(ars[3]), + return(true) + ), + gf_irr:rat(ars[3]) + ) + ), + + gf_char:ars[1], + gf_one:rat(1,x), + gf_order:gf_char^gf_exp-1, + + m:makelist(coeff(gf_irr,x,i),i,0,gf_exp), + gf_list:[[first(m),0]],j:1, + for i:2 thru gf_exp+1 do if m[i]=0 then j:j+1 else ( gf_list:endcons([m[i],j],gf_list), j:1 ), + + if not(primep(gf_char)) then error("ERROR: Gf_Char must be a prime number.") + else + modulus:gf_char, + if GF_IRREDUCIBILITY_CHECK and + hipow(args(factor(ars[3]))[1],x)#hipow(rat(ars[3]),x) then + error("ERROR: Polynomial is not irreducible"), + + if not(largefield) then + ( + pg:mkpowers(), + lg:mklogs() + ) + else + ( + if GF_VERBOSE then + print("finding a primitive element..."), + + gf_prim:rat(gf_findprim(),x), + if GF_VERBOSE then + print("...primitive element found.") + + ), + modulus:false, /* it resets the modulus */ + return(true) + + )$ + + +/* Prints out information about the field */ +gf_info():=block( + print("Prime gf_char value: ",gf_char), + print("Exponent: ", gf_exp), + print("Multiplicative order: ",gf_order), + print("Irreducible polynomial: ",gf_irr), + print("Primitive element: ",gf_prim), + if (largefield) then + print("Largefield flag is true; powers and logarithms not computed.") + else + print("Largefield flag is false; powers and logarithms computed."), + disp() +)$ + + +/* To test irreducibility, use factor! */ +/* modulus:prime; */ +/* px: x^n+.....; */ +/* if first(args(factor(px)))=(x^n) then ... */ + +/* isprimitive(p):=block([power:gf_char^gf_exp-1,flag1:false,flag2:false,f,fl,m], + if remainder(x^power-1,p)=0 then flag1:true, + f:ifactors(power), + fl:makelist(f[i][1],i,1,length(f)), + m:makelist(remainder(x^(power/fl[i])-1,p),i,1,length(f)), + if not(member(0,m)) then flag2:true, + return(flag1 and flag2) + )$ */ + + +/* Returns all coefficients of a polynomial, as a list of designated length. +The elements of the list are values in the range 0, 1, 2, ..., gf_char-1. */ +coeffs(poly,n):=block([m:makelist(coeff(poly,x,n-i),i,0,n)], + return(maplist(lambda([x],mod(x,gf_char)),m)) + )$ + + +/* Turns a list into a number, by treating the elements of the list as +coefficients of a polynomial */ + + +list2num(l,n):=block([ln:length(l)],sum(l[i]*n^(ln-i),i,1,ln))$ + + +/* Turns a polynomial into a number by evaluating it for the gf_char value */ +poly2num(p):=subst(gf_char,x,p); + + +/* Turns a number into a list, where the elements of the list are the "digits" +of the number in gf_char b */ +num2list(n,b):=block([lst:[],a:n], + for i:1 while a#0 do ( + lst:cons(?mod(a,b),lst), + a:(a-lst[1])/b + ), + return(lst) +); + + +rnum2list(n,b):=block([lst:[],a:n], + for i:1 while a#0 do ( + lst:endcons(?mod(a,b),lst), + a:(a-last(lst))/b + ), + return(lst) +); + + +/* Returns a polynomial in x whose coefficients are given by the list */ +list2poly(l):=block([s:length(l)], + return(sum(l[i]*x^(s-i),i,1,s))); + +poly2list(poly):=block([i,s:hipow(poly,x)], + return(makelist(coeff(poly,x,s-i),i,0,s))); + + +/* Turns a number into a polynomial - this is the inverse of the poly2num command */ +num2poly(n):=list2poly(num2list(n,gf_char)); + + +/* Creates a power table for the field, where the i-th element is the numerical +equivalent of the field element e^i, where e is a primitive element */ +mkpowers():=block([poly], + if not(largefield) then + gf_prim:gf_findprim(), + gp:makelist(0,i,1,gf_order), + gp[1]:1, + poly:1, + for i:2 thru gf_order do + ( + poly:gf_eval(fasttimes(gf_prim,poly)), + gp[i]:poly2num(list2poly(coeffs(poly,gf_exp))) + ), + return(gp) + ); + + +/* Creates a log table: the inverse lookup of the power table */ +mklogs():=block([lg:makelist(0,i,1,gf_order)], + for i:2 thru gf_order do lg[gp[i]]:i-1, + return(lg) + ); + + +/* Calculates powers using the standard "repeated squaring" algorithm */ +gf_binpower(p,n):=block([t:gf_one,ln], + ln : ?integer\-length(n), p:rat(p,x), + for i:1 thru ln do ( + if ?logbitp(ln-i,n) then t:gf_eval(fasttimes(gf_eval(fasttimes(t,t)),p)) + else t:gf_eval(fasttimes(t,t)) + ), + return(t) + ); + + +/* Creates an array of couples [a!, 1/(a!)] mod p */ +fact_array(p):=block([i,v2], +v2:make_array(fixnum,p,2), +for i:0 thru (p-2) do (v2[i,0]:1,v2[i,1]:1), +v2[p-1,0]:-1,v2[p-1,1]:-1, +if (p>3) then ( + for i:2 thru (p-1) do v2[i,0]: mod(i*v2[i-1,0],p), + for i:2 thru (p-2) do v2[i,1]: mod(((-1)^(p-i))*v2[p-i-1,0],p) +), +return(v2) +); + + +/* Calculates the product a(a+1)(a+2)...(b-1)b in Z_p */ +p_prod(a,b,p):=block([i,j,k,s], +if ((a=1) and (b=0)) then return(1), +if (a=b) then return(mod(a,p)), +if ((a=1) and (b=p-1)) then return(p-1), +if ((a=2) and (b=p-1)) then return(p-1), +s:1, +for i:a thru b do s:mod(s*i,p), +return(s) +); + + +/* Calculates (n!)^(-1) in Z_p using Wilson Theorem */ +/* This algorithm DOES NOT require explicit inversion through gcd() */ +inverse_fact(n,p):=block([i,j,k], +if ((n=0) or (n=1)) then return(1), +if (n=p-1) then return(p-1), +return(mod(-p_prod(n+1,p-1,p),p)) +); + + +/* Calculates the maximum exponent s for which p^s divides n! */ +max_pow(n,p):= block([i,j,k,s], +if (nmax_pow(n,p)) then return(0), +a:mod(n,p), na:mod(floor(n/p),2), +b:mod(m,p), nb:mod(floor(m/p),2), +c:mod(m-n,p), nc:mod(floor((m-n)/p),2), +return(?mod(p_prod(1,b,p)*inverse_fact(a,p)*inverse_fact(c,p)*(-1)^(na+nb+nc),p)) +); + + +/* p_powers(p)[a+1][b+1] = a^b in Z_p */ +p_powers(p):=block([i,j,k,l,v2:makelist(makelist(1,i,1,p),i,1,p)], +for i:1 thru p do v2[i][1]:1, +for i:1 thru p do v2[i][2]:i-1, +for i:1 thru p do v2[i][p]:1, +v2[1][1]:0, +v2[1][p]:0, +if (p>4) then + ( + for j:3 thru p-1 do + ( + for i:1 thru p do + v2[i][j]:?mod((i-1)*v2[i][j-1],p) + ) + ), +return(v2) +); + + +/* p_thagora[a+1][b+1] = a*b in Z_p */ +p_thagora(p):=block([i,j,k,l,v3:makelist(makelist(1,i,1,p),i,1,p)], + for j:1 thru p do v3[1][j]:0, + for j:1 thru p do v3[j][1]:0, + for j:1 thru p do v3[2][j]:j-1, + for j:1 thru p do v3[j][2]:j-1, + if (p>3) then + for j:3 thru p do ( + for i:3 thru p do v3[i][j]:?mod((i-1)+v3[i][j-1],p) + ), +return(v3) +); + + +/* Creates an array of polynomials x^(gf_char^h) with 0<=hmax) then max:ps[i], + rmatrix:zeromatrix(nf,max), + for i:1 thru nf do + ( + rmatrix[i,1]:1,rmatrix[i,2]:gf_binpower(a,order/ps[i]), + for j:3 thru ps[i] do + rmatrix[i,j]:gf_eval(fasttimes(rmatrix[i,j-1],rmatrix[i,2])) + ), + as:makelist(0,i,1,nf), + ms:makelist(0,i,1,nf), + for i:1 thru nf do + ( + b:makelist(p,j,1,alpha[i]), + xs:makelist(0,j,1,alpha[i]), + sum:0, + for j:1 thru alpha[i] do + ( + b[j]:gf_div(p,gf_binpower(a,sum)), + power:gf_binpower(b[j],order/(ps[i])^j),k:1,flag:true, + while k<=ps[i] and flag do (if(rmatrix[i,k]=power) then (xs[j]:k-1,flag:false), k:k+1), + sum:sum+xs[j]*ps[i]^(j-1) + ), + as[i]:sum, + ms[i]:ps[i]^alpha[i] + ), + return(chrem(as,ms)) + ); + + + +/* Routines related to polynomials over finite fields */ +polygf_eval(gf_elem,varname) := + sum(gf_eval(ratcoeff(rat(gf_elem,varname),varname,i))*varname^i, + i,0,hipow(gf_elem,varname)); + + + +/* Pohlig Hellmann with Pollard Rho algorithm */ +jump(poly,polyl1,polyl2,ele,gen,order):= + block([s:mod(ratsubst(0,x,poly),3)], + if s=1 then + ( + poly:gf_eval(fasttimes(poly,gen)), + polyl2:polyl2+1 + ) + else + if s=2 then + ( + poly:gf_eval(fasttimes(poly,poly)), + polyl1:?ash(polyl1,1), polyl2:?ash(polyl2,1) + ) + else + ( + poly:gf_eval(fasttimes(ele,poly)), + polyl1:polyl1+1 + ), + return([poly,polyl1,polyl2]) + ); + + +kang(ele,gen,order):= + block( + [newl1:0,newl2:0,oldl1:0,oldl2:0,new:rat(1,x),old:rat(1,x), + diff1,diff2,ll,unflag:true,index:true], + if (ele=1) then + return(0), + if (ele=gen) then + return(1), + while unflag do + ( + ll:jump(new,newl1,newl2,ele,gen,order), + new:first(ll), + newl1:second(ll), + newl2:last(ll), + index:not(index), + if index then + ( + ll:jump(old,oldl1,oldl2,ele,gen,order), + old:first(ll), + oldl1:second(ll), + oldl2:third(ll) + ), + + diff1:?mod(newl1-oldl1,order), + diff2:?mod(newl2-oldl2,order), + if (diff1#0 or diff2#0) and gf_eval(old-new)=0 then + unflag:false + ), + /* print(ele," ",gen," - collision found with ",eg), */ + /* if (a=0) then error("Zero") else */ + return(mod(-diff2*inv_mod(diff1,order),order)) + ); + + +gf_ind(some):= + if some=0 then + ( + if GF_WARNING then + ( + print("WARNING: logarithm of zero"), + -inf + ) + ) + else + ( + if some=1 then + 0 + else + ( + if gf_exp>1 then + kang_log(some) + else + kang_logp(some) + ) + ); + + +kang_log(some):= + block( + [f,primes,multiplicity,ilist:[],i,j,len,p,t,a,gen,ord,q], + f:ifactors(gf_order), + primes:map(first,f), + multiplicity:map(last,f), + len:length(multiplicity), + some:rat(some,x), + for i:1 thru len do /* ciclo per ogni primo */ + ( + p:primes[i], + gen:gf_binpower(gf_prim,gf_order/p), + t:rat(some,x), ord:0, + for j:1 thru multiplicity[i] do /* Hensel Lifting */ + ( + q:p^(j-1), + a:kang(gf_binpower(t,gf_order/(p*q)),gen,p), + ord:ord+a*q, + t:gf_eval(fasttimes(some,gf_inv(gf_binpower(gf_prim,ord)))) + ), + ilist:endcons(ord,ilist) + ), + if GF_VERBOSE then + print(ilist), + return(chrem(ilist,map(lambda([x],first(x)^last(x)),f))) +); + + +/* Complessita' : detta C la cardinalita' del campo, si hanno in media Osoft(C^(1/t)) operazioni, */ +/* dove t=log(C)/log(q), dove q e' il piu' grande primo che divide C */ +/* diff1,diff2,ll, --- allocare o non allocare? non cambia niente, sembra */ + + +/* Berlekamp-Massey Algorithm */ +bm(seq):= + block( + [m:length(seq),r,r0,r1,v,v0:rat(0,x),v1:rat(1,x),q,h,d,p], + r0:rat(x^m), + r1:rat(sum(seq[i]*x^(i-1),i,1,m)), + h:hipow(r1,x), + while (2*h>=m) do + ( + d:divide(r0,r1,x), + q:rat(first(d),x), + r:rat(last(d),x), + v:rat(v0-q*v1), + v0:v1, + v1:v, + r0:r1, + r1:r, + h:hipow(r1,x) + ), + d:max(1+h,hipow(v1,x)), + p:rat((x^d)*ratsubst(1/x,x,v1)), + h:hipow(p,x), + return(rat(p/coeff(p,x,h))) + ); + + +/* Generator for Fp --- semplice ma abbastanza inefficiente */ +fpgen(p):=block([unflag:true,n:2,t:x^(p-1)], modulus:p, + while unflag do if first(args(factor(t-n)))=t then unflag:false else n:n+1, + modulus:false, return(n)); + + + +/* Questa e' meglio, ma il bieco trucco di bypassare gf_char e' un po' zozzo */ +/* gf_gen */ +gf_findprimp(p):= + block( + [primes:map(first,ifactors(p-1)),len,unfound:true,unflag:true,i,b:2,og], + len:length(primes), + og:gf_char, + gf_char:p, + while unfound do + ( + i:1, + while i<=len and ffastpower(b,(p-1)/primes[i])#1 do + i:i+1, + if i=(len+1) then + unfound:false + else + b:next_prime(b) + ), + gf_char:og, + return(b) + ); + + +/* Questa e' meglio, ma il bieco trucco di bypassare gf_char e' un po' zozzo */ +/* gf_ggen */ +gf_findprimp_alt(p):= + block([primes:map(first,ifactors(p-1)), + len,unfound:true,unflag:true,i,b:prev_prime(p),og], + len:length(primes), + og:gf_char, + gf_char:p, + while unfound do + ( + i:1, + while i<=len and ffastpower(b,(p-1)/primes[i])#1 do + i:i+1, + if i=(len+1) then + unfound:false + else + b:prev_prime(b) + ), + gf_char:og, + return(b) + ); + + + +gf_isprimp(a):= if a=0 then false else gf_isgen(a,gf_char); +/* Check if a has maxmimum multiplicative order in F_p */ + +/* gf_isgen */ +gf_isgen(a,p):= + block([primes:map(first,ifactors(p-1)),len,i:1,temp], + temp:gf_char, gf_char:p, len:length(primes), + while i<=len and ffastpower(a,(p-1)/primes[i])#1 do + i:i+1, + gf_char:temp, + if i=(len+1) then + return(true) + else + return(false) + ); + + +/* ricerca binaria in una lista ordinata crescente - complessità massima ?integer\-length(length(list)) accessi */ +/* l'allocazione di liste non è ancora abbastanza efficiente da permettere un'implementazione parziale di un crivello ... */ +/* comunque può essere utilizzata per accelerare il gf_ind originario */ +binsearch(elem,list):= + block( + [l:length(list),l2,check,pos,k:1,j], + l2:?integer\-length(l)-1, + if GF_VERBOSE then + print(l2), + pos:?ash(2,l2-1), + while kl) then + ( + pos:pos-?ash(2,l2-k)+?ash(2,l2-k-1), + k:k+1 + ) + else + ( + check:list[pos], + if check=elem then + return(pos) + else + if check>elem then + pos:pos-?ash(2,l2-k)+?ash(2,l2-k-1) + else + if check x*p(x) (mod x^3+bx+a) */ + /* (0 1 0) It uses only 3 parameters (F_22,F_23,F_32) */ + /* that are sufficient to completely describe F^j for any j; */ + /* it returns (F^m)_22, corresponding to the evaluation of */ + /* x^m (mod x^3+bx+a) */ + /* in x=0. */ + f3power(a,b,p,m):= + block([v_22:1,v_23:0,v_32:0, + w_22:1,w_23:0,w_32:0, + c,i,j,k,l,n,index], + if m=0 then + return(1), + b:polymod(b,p), + a:polymod(a,p), + c:inv_mod(-a,p), + j:?integer\-length(m), + for i:1 thru j do + ( + k:polymod(v_23+b*v_32,p), + l:polymod(?ash(v_22,1),p), + if ?logbitp(j-i,m) then + ( + n : polymod(a*v_32,p), + w_22 : polymod(l*v_23-n*v_32,p), + w_32 : polymod(v_32*(k+v_23)+v_22*v_22,p), + w_23 : polymod(k*k-l*n-b*w_32,p) + ) + else + ( + w_22 : polymod(v_32*(k+v_23)+v_22*v_22,p), + w_23 : polymod(l*v_23-a*v_32*v_32,p), + w_32 : polymod(l*v_32+c*k*k,p) + ), + v_22:w_22, + v_23:w_23, + v_32:w_32 + ), + return(v_22) + )$ + + + /* This subroutine returns (1 0) A^(m) (1 0) mod p, where */ + /* ( 0 -a ) */ + /* A = ( 1 -b ) */ + /* i.e the m-th term of the recurrence */ + /* A_0 = 1, A_1 = 0, A_{n+2} = -b A_{n+1} - a A_{n} */ + /* with characteristic polynomial x^2 + b x + a */ + f2power(a,b,p,m):=block([v_11:0,v_21:1,w_11,w_21,u,v,i,index], + /* if m<2 then return(1-m), */ + /* b:polymod(b,p),a:polymod(a,p), */ + index:?integer\-length(m), + for i:2 thru index do + ( + if ?logbitp(index-i,m) then + ( + u:-a*v_21, + v:v_11-b*v_21, + w_11: polymod(u*(v+v_11),p), + w_21: polymod(v*v+v_21*u,p) + ) + else + ( + u:v_11*v_11, v:v_21*v_21, + w_11: polymod(u-a*v,p), + w_21: polymod((v_11+v_21)^2-(u+(b+1)*v),p) + ), + v_11:w_11, + v_21:w_21 + ), + return(mod(v_11,p)) + )$ + + + /* Stickelberger-Redei irreducibility test for cubic polynomial f(x)=x^3+bx+a */ + /* f(x) is irreducible over F_p iff its discriminant D=-4b^3-27a^2 */ + /* is a quadratic residue AND 2*(sqrt(D)+sqrt(-27a^2))^2 is NOT a cubic residue. */ + redei(a,b,p,ome,p3):= + block([d,g,y,r], + d:polymod(-4*b^3-27*a^2,p), + if jacobi(d,p)#1 then + return(false), + g:polymod(msqrt(d,p)[1]+3*a*ome,p), + y:polymod(?ash(g*g,1),p), + r:fastpower(y,p3,p), + if mod(r,p)=1 then + return(false) + else + return(true) + )$ + + + /* For VERY large p, it might be useful to factor (p-1) into prime factors */ + /* (p-1) = 2^(a_1) 3^(a_2) ... q_l^(a_l) */ + /* then use a factor-addition-chain instead of the binary one: */ + /* r:y, for i:l downto 1 do ( */ + /* r:polymod(fastpower(r,q_l^(a_l),p),p), */ + /* if r=1 then return(false) */ + /* ), if r=1 then return(true) else return(false) */ + /* to have great chances to shorten the cubic-residue test. */ + + + /* If a is a quadratic residue in F_p, this routine returns */ + /* two integers in [0, p-1] such that their squares */ + /* are congruent to a (mod p). */ + /* */ + /* If b^2-4a is a quadratic non-residue mod p, the polynomial */ + /* x^2 - bx + a */ + /* has two roots in F_(p^2) = (Z/pZ[x])/(x^2-bx+a) */ + /* the former being the Frobenius conjugate of the latter */ + /* y = y^p */ + /* so that sqrt(a)=y^((p+1)/2) for Viete's theorem. */ + /* The point is to compute */ + /* mu = (b/2 + sqrt(b^2-4a)/2)^((p+1)/2) = J + K sqrt(b^2-4a) */ + /* in a fast way. We notes that if a is a quadratic residue */ + /* mu can't be a proper element of the field extension */ + /* F_p (sqrt(b^2-4a)) */ + /* so we must have K=0, or, in the same way, */ + /* mu = (1/2) { (b/2 + sqrt(delta)/2)^((p+1)/2) */ + /* +(b/2 - sqrt(delta)/2)^((p+1)/2 } */ + /* that is the (p+1)/2-th term of the sequence */ + /* A_0 = 1, A_1 = b/2, A_{n+2}=b*A_{n+1}-a*A_{n} */ + /* All we need is the (p+1)/2-power of the matrix */ + /* ( b -a ) */ + /* A = ( 1 0 ) over Z/pZ */ + /* The subroutine "mpower" returns it with about 8 log(p) */ + /* multiplications and 4 log(p) mod-reductions in Z/pZ, */ + /* using the standard "repeat-squaring" algorithm. */ + + /* Field extension algorithm for square-root extraction through companion matrix powers */ + /* returns two integers in [0,p-1] whose square are congruent to a (mod p) */ + msqrt(a,p):= + block([b:0,term,nrflag:false], + if (mod(a,p)=0) then + return([0,0]), + /* if not(primep(p)) then error("ERROR: Second argument must be a prime number."), */ + if jacobi(a,p)#1 then + error("ERROR: First argument must be a quadratic residue."), + if p=2 then + return(mod(a,2)), + while not(nrflag) do + ( + b:b+1, + if jacobi(b*b-4*a,p)=-1 then + nrflag:true + ), + /*print(b,"^2 - 4*",a," is a quadratic non-residue"),*/ + term:mod(f2power(a,b,p,?ash(p+1,-1)),p), + return([term,p-term]) + )$ + + + /* Shank's algorithm for square-root extraction */ + /* returns two integers in [0,p-1] whose square are congruent to a (mod p) */ + ssqrt(a,p):= + block([i,j,nrflag:false,b:0,s:0,t,q:p-1,alpha,r,d], + if (mod(a,p)=0) then + return([0,0]), + /* if not(primep(p)) then error("ERROR: Second argument must be a prime number."), */ + if jacobi(a,p)#1 then + error("ERROR: First argument must be a quadratic residue."), + if p=2 then + return(mod(a,2)), + while not(nrflag) do + ( + b:b+1, + if jacobi(b,p)=-1 then + nrflag:true + ), + while not(?logbitp(0,q)) do + ( + s:s+1, + q:?ash(q,-1) + ), + t:q, + alpha:inv_mod(a,p), + c:fastpower(b,t,p), + r:fastpower(a,?ash((t+1),-1),p), + for i:1 thru s-1 do + ( + d:polymod(polymod(r*r,p)*alpha,p), + for j:1 thru (s-i-1) do + d:polymod(d*d,p), + if polymod(d+1,p)=0 then + r:polymod(r*c,p), + c:polymod(c*c,p) + ), + r:mod(r,p), + return([r,p-r]) + )$ + + + /* Field extension algorithm for cubic-root extraction */ + /* For a cubic residue a and a prime p=1(mod 3) mcbrt finds */ + /* an irreducible polynomial of the form x^3+bx+a over F_p */ + /* so that -a=x^(p^2+p+1) and returns x^((p^2+p+1)/3) */ + /* computed over F_(p^3) = (F_p)/(x^3+bx+a) */ + /* This subroutine returns three integers in [0,p-1] */ + /* whose third-power are congruent to a (mod p) */ + scbrt(a,p):=block( + [b:1,term,h1,h2,h3,q,c,c_1,c_2,om,omega_1,p3], + if (mod(a,p)=0) then + return(0), + /*if not(primep(p)) then error("ERROR: Second argument must be a prime number."),*/ + if p=2 then + return(mod(a,2)), + if mod(p,3)=2 then + return(fastpower(a,(?ash(p,1)-1)/3,p)), + om:msqrt(-3,p), p3:(p-1)/3, + if fastpower(a,p3,p)#1 then + error("ERROR: First argument must be a cubic residue."), + while not(redei(a,b,p,om[1],p3)) do + b:b+1, + q:x^3+b*x+a, + h1:polypower(x,p,q,p), + h2:polypower(h1,p3,q,p), + h3:polypower(x,(?ash(p,1)+1)/3,q,p), + c:polymod(-remainder(h2*h3,q),p), + c:mod(c,p), + omega_1:mod((-1+om[1])*(?ash(p+1,-1)),p), + c_1:mod(omega_1*c,p), + c_2:mod(-c-c_1,p), + return([c,c_1,c_2]) + )$ + + + /* Field extension algorithm for cubic-root extraction */ + /* through companion matrix powers. This subroutine returns three integers */ + /* in [0,p-1] whose third-power are congruent to a (mod p) */ + mcbrt(a,p):=block( + [b:1,c,c_1,c_2,om,omega_1,p3], + if (mod(a,p)=0) then + return(0), + /*if not(primep(p)) then error("ERROR: Second argument must be a prime number."),*/ + if p=2 then + return(mod(a,2)), + if mod(p,3)=2 then + return(fastpower(a,(?ash(p,1)-1)/3,p)), + om:msqrt(-3,p), p3:(p-1)/3, + if fastpower(a,p3,p)#1 then + error("ERROR: First argument must be a cubic residue."), + while not(redei(a,b,p,om[1],p3)) do + b:b+1, + c:mod(-f3power(a,b,p,(1+p*(p+1))/3),p), + omega_1:mod((-1+om[1])*(?ash(p+1,-1)),p), + c_1:mod(omega_1*c,p), + c_2:mod(-c-c_1,p), + return([c,c_1,c_2]) + )$ + + /* For each prime p in the form 4k+1 we find two positive integers */ + /* a and b such that p=a^2+b^2. Useful to extend a Z-factorization */ + /* into a Z[i]-factorization (order of Gaussian integers) */ + + qsplit(p):= + block([m,a,b:1,c,d,e,f,k,j], + if (p=2) then + return([1,1]), + m:msqrt(-1,p), + if (m[1] < m[2]) then + a:m[1] + else + a:m[2], + k:(a^2+1)/p, + while (k>1) do + ( + k:(a^2+b^2)/p, + c:polymod(a,k), + d:polymod(b,k), + j:(c^2+d^2)/k, + e:(a*c+b*d)/k, + f:(b*c-a*d)/k, + a:abs(e), + b:abs(f), + k:j + ), + return([a,b]) + )$ + + + /* For each prime p in the form 3k+1 we find two positive integers */ + /* a and b such that p=a^2+ab+b^2. Useful to extend a Z-factorization */ + /* into a Z[omega]-factorization (order of Eisenstein integers) */ + csplit(p):= + block( + [m,a,b,c,d,t,x,y], + if (p=3) then + return([1,1]), + m:msqrt(-3,p), + if (mod(m[1],2)=0) then + b:m[2] + else + b:m[1], + a:(b^2+3)/(4*p), + c:p, + x:0, + y:1, + while (b#1) do + ( + if (a>c) then + ( + d:a, + a:c, + c:d, + b:-b, + d:x, + x:-y, + y:d + ), + t:floor(b/?ash(a,1)), + b:b-?ash(a*t,1), + c:c-t*(b+a*t), + x:x+t*y + ), + if (x<0) then + if (y<-x) then + x:-(x+y) + else + ( + x:-x, + y:y-x + ), + if (y<0) then + if (x<-y) then + y:-(x+y) + else + ( + y:-y, + x:x-y + ), + return([x,y]) + ); + + +/* Fast Lucas Numbers Computation */ + fastlucas(n):=block([O:2,L:?integer\-length(n),i,f0:2,f1:1,u,v], + for i:1 thru L do ( + u:f0^2, v:f1^2, + if ?logbitp(L-i,n) then (f1:v+O, f0:f1-u+O, O:-2 ) + else (f0:u-O, f1:v+O-f0, O:2 )), + return(f0) + ); + + /* Fast Fibonacci Numbers Computation */ + fastfib(n):=block([O:2,L:?integer\-length(n),i,f0:2,f1:1,u,v], + for i:1 thru L do ( + u:f0^2, v:f1^2, + if ?logbitp(L-i,n) then (f1:v+O, f0:f1-u+O, O:-2 ) + else (f0:u-O, f1:v+O-f0, O:2 )), + return((?ash(f1,1)-f0)/5) + ); + + diff --git a/share/tests/hl/highlight.mup b/share/tests/hl/highlight.mup new file mode 100644 index 0000000..ed5a03d --- /dev/null +++ b/share/tests/hl/highlight.mup @@ -0,0 +1,103 @@ +// This is a MUP highlighting test. +// Mup is a shareware music publisher from www.arkkra.com + +// contexts +score +music +staff 1 +voice 1 3 + +top +top2 +bottom +bottom2 +grids + +headshapes + + +header +footer +header2 +footer2 + +// parameters and values +score + units = cm; + key = 3#minor + key = 3# minor + rehstyle=circled + + + + +mussym above all: 1 "ferm" ; + +define NAME +// this is a macro definition, these are collapsable +@ + +ifdef NAME +// this is conditionally "compiled" +endif + +ifndef NAME +// this is conditionally "compiled" when the macro has not been defined +else +// else clause +endif + + +// Various Tests + +// tablature +1: e ^f; f; b ^c5; c#5; +bar + +1: d+^e+ g^a; e+a; g ^/; c ^/ c+^/; +bar + +// cross-staff stems +1: 1e+g+c++; +2: cc+; ee+; g with g+ above; with c+c++ above; +bar + +1: 2+4ceg;4; // tie implied by added time values + +// slurs +1: 2f a c+; dbd+; +bar +1: 2fac+ slur; dbd+; +bar + +// alternation +1: 2c alt 2; 2c+;2g; +bar + +// bar to draw if repeatstart happens to be on new line +(dblbar) repeatstart +1: [up]8f bm with staff below;a;4s ebm;4s bm with staff below;8b;[len 11]d ebm; +2: 4s bm with staff above;8a;b ebm;[down;len 14]b bm with staff above;d;4s ebm; +bar + +// locations +3: 2cf; [=h] egc+; +1: [cue; with >; =_ch] fa; + + +roll up 1 1 to 1 2: 2; 4; +roll down 1 1 to 1 2: 2; 4; + +lyrics above 1,3 ; below 2,4 ; between 5&6 : "<1. >Hi, hi"; + +title "page \% of \#" + +// shaped whole rests +1: 4mr; // use a quarter rest symbol +1: 1/4mr; // use a quadruple whole rest symbol +2: 2.. mr; // use a double-dotted half rest + +// tuplets +1: {4f; g;}3num,4.+2. +bar + diff --git a/share/tests/hl/highlight.pb b/share/tests/hl/highlight.pb new file mode 100644 index 0000000..5560233 --- /dev/null +++ b/share/tests/hl/highlight.pb @@ -0,0 +1,87 @@ +; This is a test file for kate's PureBasic highlighting. + +; BMP2x Converter by Sven Langenkamp + +UseJPEGImageEncoder() +UsePNGImageEncoder() + +Declare Convert(JPEG) + +Enumeration 1 + #JPEG + #PNG +EndEnumeration + +; BEGIN section + + +; END + +Global Count +Global file.s +Global filename.s +Global fileext.s +Global OutputFormat +Global JPEGQuality + +Count = 0 +OutputFormat = 1 +JPEGQuality = -1 + +; MAIN PROGRAM------------------------------------------------------------------ + +;Request Options +PrintN("Output Format") +PrintN(" [1] JPEG") +PrintN(" [2] PNG") +Print ("> ") +OutputFormat = Int(Input()) + +Select OutputFormat + Case #JPEG: + fileext = ".jpg" + ;Request JPEG Quality + PrintN("") + PrintN("JPEG Quality") + PrintN(" [0-10]") + Print ("> ") + JPEGQuality = Int(Input()) + + Case #PNG: + fileext = ".png" +EndSelect + +;Convert all BMP files in the current directory +ExamineDirectory(0, "", "*.bmp") +While NextDirectoryEntry() + file = DirectoryEntryName() + filename = GetFilePart(file) + + If LoadImage(0, file) + Select OutputFormat + Case #JPEG: + Convert(JPEGQuality) + + Case #PNG: + Convert(-1) + EndSelect + Count = Count +1 + EndIf + +Wend + +PrintN(Str(Count) + " files converted") +CloseConsole() + +; PROCUDURES-------------------------------------------------------------------- + +Procedure Convert(JPEG) + Shared filename, fileext + + If JPEG > -1 + SaveImage(0, filename + fileext, #PB_ImagePlugin_JPEG, JPEG) + Else + SaveImage(0, filename + fileext, #PB_ImagePlugin_PNG) + EndIf + PrintN(file + " converted to " + filename + fileext) +EndProcedure \ No newline at end of file diff --git a/share/tests/hl/highlight.php b/share/tests/hl/highlight.php new file mode 100644 index 0000000..d604e36 --- /dev/null +++ b/share/tests/hl/highlight.php @@ -0,0 +1,23 @@ + + + + + + test"; ?> + + + \ No newline at end of file diff --git a/share/tests/hl/highlight.pike b/share/tests/hl/highlight.pike new file mode 100644 index 0000000..2f63144 --- /dev/null +++ b/share/tests/hl/highlight.pike @@ -0,0 +1,24 @@ +#! /bin/env pike + +/* This file is a syntax highlight test for Kate. + * FIXME: Improve it to contain more (and more unusual) syntax examples. + */ + + +#define PIKE_ON_THE_WEB /* Is this address correct? */ "http://pike.ida.liu.se/" + + +int main(int argc, array(string) args) +{ + // Write funny things with Pike :) + write(`+("Command line arguments (%d of them): ", @map(args, `+, " ")) + "\n", argc); + + write("\nVisit Pike site at %s\n\n", PIKE_ON_THE_WEB); + + for (int i = 1; i <= 3; i++) + write(":" + ")" * i + " "); + + write("\n" + ({"Bye", "bye"}) * "-" + "!\n"); + + return 0; +} diff --git a/share/tests/hl/highlight.pl b/share/tests/hl/highlight.pl new file mode 100644 index 0000000..991d1fe --- /dev/null +++ b/share/tests/hl/highlight.pl @@ -0,0 +1,44 @@ +#!/usr/bin/perl -w +# This is a pseudo Perl file to test Kate's Perl syntax highlighting. +# TODO: this is incomplete, add more syntax examples! + +sub prg($) +{ + my $var = shift; + + $var =~ s/bla/foo/igs; + $var =~ s!bla!foo!igs; + $var =~ s#bla#foo#igs; + $var =~ tr/a-z/A-Z/; + ($match) = ($var =~ m/(.*?)/igs); + + $test = 2/453453.21; + $test /= 2; + + print qq~d fsd fsdf sdfl sd~ + + $" = '/'; + + $foo = <<__EOF; +d ahfdklf klsdfl sdf sd +fsd sdf sdfsdlkf sd +__EOF + + $x = "dasds"; + + next if( $match eq "two" ); + next if( $match =~ /go/i ); + + @array = (1,2,3); # a comment + @array = qw(apple foo bar); + push(@array, 4); + %hash = (red => 'rot', + blue => 'blau'); + print keys(%hash); +} + +sub blah { +} + +&blah; +prg("test"); diff --git a/share/tests/hl/highlight.pov b/share/tests/hl/highlight.pov new file mode 100644 index 0000000..0bb3077 --- /dev/null +++ b/share/tests/hl/highlight.pov @@ -0,0 +1,76 @@ +//BEGIN TEST +// test scene for POV-Ray syntax highlighting + +/* test comment */ + +/* nested /* comments */ do not work */ + +#version 3.5; +//END +global_settings { assumed_gamma 1.0 } + +// ---------------------------------------- + +camera { + location <5.0, -12.0, 2.0> + up z sky z + look_at <0.0, 0.0, 0.5> + angle 40 +} + +sky_sphere { + pigment { + gradient z + color_map { + [0.0 rgb <0.6,0.7,1.0>] + [0.2 rgb <0.2,0.3,0.9>] + } + } +} + +light_source { + <3, 1, 2>*1000 + color rgb <2.2, 1.8, 1.5> +} + +// ---------------------------------------- + +#declare TEST=0; + +#ifdef (TEST) + plane { + z, 0 + texture { + pigment { + checker + color rgb 1, color rgb 0 + } + } + } +#end + +#macro Sphere(Pos, Radius) + sphere { + , Radius + texture { + pigment { color rgb 1 } + finish{ + diffuse 0.3 + ambient 0.0 + specular 0.6 + reflection 0.8 + } + } + } +#end + +#local Cnt=0; +#local Seed=seed(0); + +#while (Cnt<10000) + Sphere( + -100+*200, + 0.3+pow(rand(Seed),2)*0.7 + ) + #local Cnt=Cnt+1; +#end \ No newline at end of file diff --git a/share/tests/hl/highlight.prg b/share/tests/hl/highlight.prg new file mode 100644 index 0000000..713c605 --- /dev/null +++ b/share/tests/hl/highlight.prg @@ -0,0 +1,71 @@ +// Test file to test kate's clipper highlighting +// kate: hl Clipper; + +//BEGIN INCLUDES +#include +#include "logo.ch" + +#define PRGVERSION "0.0.1" +//END + +//BEGIN CODE +static ws, win +static driver := getDriver() +/* a multiline + comment +*/ + +function main( formName ) + local form + local fileName + + if empty(formName) + ?? "Usage: ./form_ui &\n" + CANCEL + else + fileName := formName + endif + ws := UIWorkSpace() + + form := UIForm( fileName ) + win := form:parseFile() +// ?? valtype(win),chr(10) + if win == NIL + CANCEL + endif + win:show() + + ws:run() + ws:quit() +return 0 + +/* Setting dialog */ +function settingsDialog() + ?? "TODO: Settings dialog&\n" +return + +/* About dialog */ +function aboutDialog() + local dlg := UIWindow("About", win, "aboutDlg", .F.) + local hl, lside, t, bb, bD + + hl := UIHBox(,4,8) + lside := UIVBox() + lside:add(UIImage(eas_logo_mini,.T.)) + hl:add(lside,.F.,.F.) + dlg:userSpace:add(hl,.T.,.T.) + t := UIVBox() + hl:add(t,.T.,.T.) + + t:add(UILabel("License: GPL version 2 or later")) + bb := UIButtonBar() + t:add(bb) + bD := UIButton(win, "&Close", {|o,e| dlg:close() } ) + bb:add( bD ) + + dlg:setFocus(bD) + dlg:setDefault(bD) + dlg:setPlacement( .T. ) + dlg:show() +return +//END \ No newline at end of file diff --git a/share/tests/hl/highlight.qml b/share/tests/hl/highlight.qml new file mode 100644 index 0000000..b860512 --- /dev/null +++ b/share/tests/hl/highlight.qml @@ -0,0 +1,59 @@ +import Qt 4.6 + +// some random qml snippets stolen from the qt docs + +Rectangle { + important: true + propertyAsdf: + id: container + signalA: bla + property string label + signal clicked + radius: 5; border.color: "black" + color: mouse.pressed ? "steelblue" : "lightsteelblue" + gradient: Gradient { + GradientStop { position: mouse.pressed ? 1.0 : 0.0; color: "steelblue" } + GradientStop { position: mouse.pressed ? 0.0 : 1.0; color: "lightsteelblue" } + } + MouseRegion { id: mouse; anchors.fill: parent; onClicked: container.clicked() } + Text { anchors.fill: parent; text: container.label; anchors.centerIn: parent } +} + +Rectangle { + Script { + function calculateMyHeight() { + return Math.max(otherItem.height, thirdItem.height); + } + } + + anchors.centerIn: parent + width: Math.min(otherItem.width, 10) + height: calculateMyHeight() + color: { if (width > 10) "blue"; else "red" } +} + +Rectangle { + default property color innerColor: "black" + property color innerColor: "black" + property alias text: textElement.text + property alias aliasXYZ: testElement.text + signal bar + signal bar(var blah, string yxcv) + width: 240; height: 320; + width: 100; height: 30; source: "images/toolbutton.sci" + ListView { + anchors.fill: parent + model: contactModel + delegate: Component { + Text { + text: modelData.firstName + " " + modelData.lastName + } + } + } +} + +Item { + function say(text) { + console.log("You said " + text); + } +} diff --git a/share/tests/hl/highlight.rb b/share/tests/hl/highlight.rb new file mode 100644 index 0000000..aea0f24 --- /dev/null +++ b/share/tests/hl/highlight.rb @@ -0,0 +1,572 @@ +# This file is a testcase for the highlighting of Ruby code +# It's not executable code, but a collection of code snippets +# + +require 'Config' +require 'DO/Clients' +require 'DO/DBClients' + + def CGI::escapeElement(string, *elements) + elements = elements[0] if elements[0].kind_of?(Array) + unless elements.empty? + string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/ni) do + CGI::escapeHTML($&) + end + else + string + end + end + +case inputLine + when "debug" + dumpDebugInfo + dumpSymbols + when /p\s+(\w+)/ + dumpVariable($1) + when "quit", "exit" + exit + else + print "Illegal command: #{inputLine}" +end + + +kind = case year #hi there + when 1850..1889 then "Blues" + when 1890..1909 then "Ragtime" + when 1910..1929 then "New Orleans Jazz" + when 1930..1939 then "Swing" + when 1940..1950 then "Bebop" + else "Jazz" + end + + # URL-encode a string. + # url_encoded_string = CGI::escape("'Stop!' said Fred") + # # => "%27Stop%21%27+said+Fred" + def CGI::escape(string) + string.gsub(/([^ a-zA-Z0-9_.-]+)/n) do + '%' + $1.unpack('H2' * $1.size).join('%').upcase + end.tr(' ', '+') + end + + +# Class ClientManager +# +# definition : Import, store and export the various data used by the application. +# This class is the sole interface between the application and the underlying database. + +mon, day, year = $1, $2, $3 if /(\d\d)-(\d\d)-(\d\d)/ +puts "a = #{a}" if fDebug +print total unless total == 0 + +while gets + next if /^#/ # Skip comments + parseLine unless /^$/ # Don't parse empty lines +end + +if artist == "John Coltrane" #hi there + artist = "'Trane" #hi there +end unless nicknames == "no" #hi there + +handle = if aSong.artist == "Gillespie" then #hi there + "Dizzy" + elsif aSong.artist == "Parker" then + "Bird" + else #hi there + "unknown" + end + +if aSong.artist == "Gillespie" then handle = "Dizzy" +elsif aSong.artist == "Parker" then handle = "Bird" +else handle = "unknown" +end #hi there + +if aSong.artist == "Gillespie" then + handle = "Dizzy" +elsif aSong.artist == "Parker" then + handle = "Bird" +else + handle = "unknown" +end + +if aSong.artist == "Gillespie" + handle = "Dizzy" +elsif aSong.artist == "Parker" + handle = "Bird" +else + handle = "unknown" +end + + case line + when /title=(.*)/ + puts "Title is #$1" + when /track=(.*)/ + puts "Track is #$1" + when /artist=(.*)/ + puts "Artist is #$1" +end + +case shape + when Square, Rectangle + # ... + when Circle + # ... + when Triangle + # ... + else + # ... +end + + +until playList.duration > 60 #hi there + playList.add(songList.pop) +end + +3.times do + print "Ho! " +end + +loop { + # block ... +} + +songList.each do |aSong| + aSong.play +end + +for aSong in songList + aSong.play +end + +for i in ['fee', 'fi', 'fo', 'fum'] + print i, " " +end +for i in 1..3 + print i, " " +end +for i in File.open("ordinal").find_all { |l| l =~ /d$/} + print i.chomp, " " +end + +class Periods + def each + yield "Classical" + yield "Jazz" + yield "Rock" + end +end + + +periods = Periods.new +for genre in periods + print genre, " " +end + +while gets + next if /^\s*#/ # skip comments + break if /^END/ # stop at end + # substitute stuff in backticks and try again + redo if gsub!(/`(.*?)`/) { eval($1) } + # process line ... +end + +i=0 +loop do + i += 1 + next if i < 3 + print i + break if i > 4 +end + +for i in 1..100 + print "Now at #{i}. Restart? " + retry if gets =~ /^y/i +end + +def doUntil(cond) + yield + retry unless cond +end + +i = 0 +doUntil(i > 3) { + print i, " " + i += 1 +} + +def system_call + # ... code which throws SystemCallError +rescue SystemCallError + $stderr.print "IO failed: " + $! + opFile.close + File.delete(opName) + raise +end + +class ClientManager + + # constructor + def initialize(dbase) + @dbClient = DBClient.new(dbase) + @clients = Clients.new + end + + def prout(a, b, xy="jj") 24 end + ############################################################### + # + # CLIENTS SECTION + # + ############################################################### + + # update the clients object by retrieving the related data from the database + # returns the number of clients + def refreshClients + @clients.clean + unless @sqlQuery.nil? then + @sqlQuery.selectClient.each do |row| + @clients.addClient(row[0],row[1],row[2],row[3],row[4],row[5], row[6], row[7], row[8]) + end + else + puts "SqlQuery wasn't created : cannot read data from database" + end + return @clients.length + end + + # insert a client in the database and refreshes the local clients object + # we assume that none of the arguments is null + # we assume that the client, identified by raison_sociale doesn't already exists + def addClient(raison_sociale, division, departement, adresse, cp, ville, nom_contact, tel_contact) + id = "0" + unless @sqlQuery.nil? then + id = @sqlQuery.insertClient(raison_sociale, division, departement, adresse, cp, ville, nom_contact,tel_contact) + else + puts "SqlQuery wasn't created : database update cannot be performed" + end + @clients.addClient(id, raison_sociale, division, departement, adresse, cp, ville, nom_contact, tel_contact) # synchronize local object with DB + end + + # deletes a client from the database and updates the local Clients object accordingly + def delClient(nomclient_brut) + raison_sociale, div, dep = Clients.getIdentifiers(nomclient_brut) + listeContratsExp, listeContratsSup, listeContratsProd, listePropositionsExp, listePropositionsSup = [] + + listeContratsExp = @contratsExpertise.getContratsFromClient(nomclient_brut) + listeContratsSup = @contratsSupport.getContratsFromClient(nomclient_brut) + listeContratsProd = @contratsProduits.getContratsFromClient(nomclient_brut) + listePropositionsExp = @propositionsExpertise.getPropositionsFromClient(nomclient_brut) + listePropositionsSup = @propositionsSupport.getPropositionsFromClient(nomclient_brut) + + unless @sqlQuery.nil? then + @sqlQuery.deleteClient(raison_sociale, div, dep) + + @sqlQuery.deleteContracts(Config::EXPERTISE,listeContratsExp) + @sqlQuery.deleteContracts(Config::SUPPORT,listeContratsSup) + @sqlQuery.deleteContracts(Config::PRODUIT,listeContratsProd) + @sqlQuery.deletePropositions(Config::EXPERTISE,listePropositionsExp) + @sqlQuery.deletePropositions(Config::SUPPORT,listePropositionsSup) + else + puts "SqlQuery wasn't created : database update cannot be performed" + end + @clients.delClient(raison_sociale,div,dep) + + @contratsExpertise.deleteContracts(listeContratsExp) + @contratsSupport.deleteContracts(listeContratsSup) + @contratsProduits.deleteContracts(listeContratsProd) + @propositionsExpertise.deletePropositions(listePropositionsExp) + @propositionsSupport.deletePropositions(listePropositionsSup) + end +end + + # Mixin module for HTML version 3 generation methods. + module Html3 # :nodoc: + + # The DOCTYPE declaration for this version of HTML + def doctype + %|| + end + + # Initialise the HTML generation methods for this version. + def element_init + extend TagMaker + methods = "" + # - - + for element in %w[ A TT I B U STRIKE BIG SMALL SUB SUP EM STRONG + DFN CODE SAMP KBD VAR CITE FONT ADDRESS DIV center MAP + APPLET PRE XMP LISTING DL OL UL DIR MENU SELECT table TITLE + STYLE SCRIPT H1 H2 H3 H4 H5 H6 TEXTAREA FORM BLOCKQUOTE + CAPTION ] + methods += <<-BEGIN + nn_element_def(element) + <<-END + def #{element.downcase}(attributes = {}) + BEGIN + end + END + end + + # - O EMPTY + for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT + ISINDEX META ] + methods += <<-BEGIN + nOE_element_def(element) + <<-END + def #{element.downcase}(attributes = {}) + BEGIN + end + END + end + + # O O or - O + for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD LI OPTION tr + th td ] + methods += <<-BEGIN + nO_element_def(element) + <<-END + def #{element.downcase}(attributes = {}) + BEGIN + end + END + end + eval(methods) + end + + end + +# following snippet from Webrick's log.rb +# notice the erronous handling of the query method is_a? +def format(arg) + str = if arg.is_a?(Exception) + "#{arg.class}: #{arg.message}\n\t" << + arg.backtrace.join("\n\t") << "\n" + elsif arg.respond_to?(:to_str) + arg.to_str + else + arg.inspect + end +end + +# following snippet from Webrick's httputils.rb +# Splitting regexps on several lines might be bad form, +# but not illegal in Ruby. +# This should probably be supported in the highlighting +def split_header_value(str) + str.scan(/((?:"(?:\\.|[^"])+?"|[^",]+)+) + (?:,\s*|\Z)/xn).collect{|v| v[0] } +end + +# snippet from Net::Telnet +string.gsub(/#{IAC}( + [#{IAC}#{AO}#{AYT}#{DM}#{IP}#{NOP}]| + [#{DO}#{DONT}#{WILL}#{WONT}] + [#{OPT_BINARY}-#{OPT_NEW_ENVIRON}#{OPT_EXOPL}]| + #{SB}[^#{IAC}]*#{IAC}#{SE} + )/xno) + +# following snippet from Webrick's httpresponse.rb +# the HEREDOC is not recognized as such +@body << <<-_end_of_html_ + + + #{HTMLUtils::escape(@reason_phrase)} + +

#{HTMLUtils::escape(@reason_phrase)}

+ #{HTMLUtils::escape(ex.message)} +
+_end_of_html_ + + +# snippet from Webrick's httpproxy.rb +# here we should make sure that the symbol definition ':' doesn't override +# the module operator '::' +Net::HTTP::version_1_2 if RUBY_VERSION < "1.7" + +# snippet from Webrick's cookie.rb +# the beginning of the regexp is erronously highlighted like an operator +key, val = x.split(/=/,2) + +# the following are division operators +# it's a bit tricky to keep the operator apart from the regexp +result = 8 / 4 +result /= divisor + +# 2008-06-01 regexp and division operator syntax has been fixed: +result = 8/4 # division +result = 8/foo # division +result = /8/ # regexp +result = 8//4/ # division and regexp + +10/10 # division +10/ 10 # division +10 /10 # division +10 / 10 # division + +foo/10 # division +foo/ 10 # division +foo /10/ # regexp +foo / 10 # division + +foo/10/10 # both division +total/count/2 # both division +total/(count/2) # both division + +@foo/10 # division +@foo /10 # division + +"hello"/10 # division +"hello" / 10 # division + +/regexp//10 # division +/regexp/ / 10 # division + +Math::PI/10 # division +Math::foo /rx/ # regexp + +# 2008-06-05 similar fix for modulo operator: + +10%4 # modulo +10 %4 # modulo +10% 4 # modulo +10 % 4 # modulo + +foo%4 # modulo +# foo %4 # illegal %string +foo% 4 # modulo +foo % 4 # modulo + +foo % (4) # modulo + +foo %(4) # %string +foo %q(4) # %string +foo %Q(4) # %string +foo %%4% # %string + +foo = %|blah| # GDL input +foo % %|blah| # modulo and GDL + +# mix in any way you want +result = 10//regexp//20/foo//regexp//20 + +# test cases for general delimited input +# quoted strings +%Q|this is a string| +%Q{this is a string} +%Q(this is a string) +%Q +%Q[this is a string] + +%|also a string| +%{also a string} +%(also a string) +% +%[also a string] + +# apostrophed strings +%q|apostrophed| +%q{apostrophed} +%q(apostrophed) +%q +%q[apostrophed] + +# regular expressions +%r{expression} +%r(expression) +%r +%r[expression] +%r|expression| + +# shell commands +%x{ls -l} +%x(ls -l) +%x +%x[ls -l] + +# sometimes it's useful to have the command on multiple lines +%x{ls -l | +grep test } + +# alternative syntax +`ls -l` +`echo ' '` + +# token array +%w{one two three} +%w(one two three) +%w +%w[one two three] + +# snippet from Net::IMAP +# I object to putting String, Integer and Array into kernel methods. +# While these classes are builtin in Ruby, this is an implementation detail +# that should not be exposed to the user. +# If we want to handle all std-lib classes, fine. But then they should be in their +# own std-lib keyword category. + +def send_data(data) + case data + when nil + put_string("NIL") + when String + send_string_data(data) + when Integer + send_number_data(data) + when Array + send_list_data(data) + when Time + send_time_data(data) + when Symbol + send_symbol_data(data) + else + data.send_data(self) + end +end + +# snippet from Net::POP +# class names can have numbers in them as long as they don't begin with numbers +# Ruby doesn't internally really make much of a difference between a class name and a constant + +# class aliases + POP = POP3 + POPSession = POP3 + POP3Session = POP3 + +# "member access" +POP::Session.COUNT.attribute.calc_with(2){ |arg| puts arg } + +# snippet from Net::SMTP +# This breaks the code folding. I think we would need to +# handle the '\' that continues the statement to the next line +# in some way to make these kind of things not break something. +raise ArgumentError, 'both user and secret are required'\ + unless user and secret + +# string escapes must detect escaping the escape char +str = "\\" +str = "\\\\" +# this is not part of the string +%x{echo \\\}\\} # prints \}\ +# this is not part of the command + +# these are all symbols +:abc +:abc! +:abc? +:abc= +:[] +:[]= +:@abc +:@@abc +:$abc + +# (global) vars starting with $ +$! +$@ +$; +$, +$/ +$\ +$. +$_ +$> +$< +$$ +$? +$~ +$= # deprecated +$* +$& +$` +$' +$+ diff --git a/share/tests/hl/highlight.rib b/share/tests/hl/highlight.rib new file mode 100644 index 0000000..0ec8277 --- /dev/null +++ b/share/tests/hl/highlight.rib @@ -0,0 +1,68 @@ +# bulb.rib +# Author: Scott Iverson +# Date: 6/9/95 +# + +Display "bulb.tiff" "file" "rgb" + +Projection "perspective" "fov" 25 +Format 380 380 -1 +Rotate 0 0 0 1 +Rotate -0.570093918 1 0 0 +Rotate 5.71059326 0 1 0 +Translate -1 -2 10 + +WorldBegin + LightSource "ambientlight" 1 "intensity" .4 + LightSource "distantlight" 2 "intensity" .6 "from" [0 0 0] "to" [-.3 -.2 1] + AttributeBegin + Rotate -90 1 0 0 + + ShadingInterpolation "smooth" + +# base + Surface "metal" + Color 0 0 1 + AttributeBegin + Orientation "rh" + Disk 0 .18 360 + AttributeEnd + + Cylinder .18 0 .1 360 + + Translate 0 0 .1 + + Surface "matte" + Color 1 1 0 + Hyperboloid .18 0 0 .4 0 .15 360 + + Translate 0 0 .15 + + Surface "metal" + Color 1 .7 0 + + Translate 0 0 .05 + Torus .4 .05 -90 90 360 + Translate 0 0 0.10 + Torus .4 .05 -90 90 360 + Translate 0 0 0.10 + Torus .4 .05 -90 90 360 + Translate 0 0 0.10 + Torus .4 .05 -90 90 360 + Translate 0 0 0.10 + Torus .4 .05 -90 90 360 + Translate 0 0 0.10 + Translate 0 0 -0.05 + +# the glass part + + Surface "plastic" "roughness" .4 + + Color 1 1 1 + + PatchMesh "bicubic" 13 "nowrap" 7 "nowrap" "P" [ 0.40 0.00 0 0.40 0.220913867 0 0.220913867 0.40 0 0.00 0.40 0 -0.220913867 0.40 0 -0.40 0.220913867 0 -0.40 0.00 0 -0.40 -0.220913867 0 -0.220913867 -0.40 0 0.00 -0.40 0 0.220913867 -0.40 0 0.40 -0.220913867 0 0.40 0.00 0 0.40 0.00 .9 0.40 0.220913867 .9 0.220913867 0.40 .9 0.00 0.40 .9 -0.220913867 0.40 .9 -0.40 0.220913867 .9 -0.40 0.00 .9 -0.40 -0.220913867 .9 -0.220913867 -0.40 .9 0.00 -0.40 .9 0.220913867 -0.40 .9 0.40 -0.220913867 .9 0.40 0.00 .9 1.0 0.0 1.34771533 1.0 0.552284667 1.34771533 0.552284667 1.0 1.34771533 0.0 1.0 1.34771533 -0.552284667 1.0 1.34771533 -1.0 0.552284667 1.34771533 -1.0 0.0 1.34771533 -1.0 -0.552284667 1.34771533 -0.552284667 -1.0 1.34771533 0.0 -1.0 1.34771533 0.552284667 -1.0 1.34771533 1.0 -0.552284667 1.34771533 1.0 0.0 1.34771533 1.0 0.0 1.9 1.0 0.552284667 1.9 0.552284667 1.0 1.9 0.0 1.0 1.9 -0.552284667 1.0 1.9 -1.0 0.552284667 1.9 -1.0 0.0 1.9 -1.0 -0.552284667 1.9 -0.552284667 -1.0 1.9 0.0 -1.0 1.9 0.552284667 -1.0 1.9 1.0 -0.552284667 1.9 1.0 0.0 1.9 1.0 0.0 2.45228467 1.0 0.552284667 2.45228467 0.552284667 1.0 2.45228467 0.0 1.0 2.45228467 -0.552284667 1.0 2.45228467 -1.0 0.552284667 2.45228467 -1.0 0.0 2.45228467 -1.0 -0.552284667 2.45228467 -0.552284667 -1.0 2.45228467 0.0 -1.0 2.45228467 0.552284667 -1.0 2.45228467 1.0 -0.552284667 2.45228467 1.0 0.0 2.45228467 0.552284667 0 2.9 0.552284667 0.305018353 2.9 0.305018353 0.552284667 2.9 0 0.552284667 2.9 -0.305018353 0.552284667 2.9 -0.552284667 0.305018353 2.9 -0.552284667 0 2.9 -0.552284667 -0.305018353 2.9 -0.305018353 -0.552284667 2.9 0.00000000 -0.552284667 2.9 0.305018353 -0.552284667 2.9 0.552284667 -0.305018353 2.9 0.552284667 0 2.9 0.001 0 2.9 0.0010 0.000552284667 2.9 0.000552284667 0.001 2.9 0 0.0010 2.9 -0.000552284667 0.0010 2.9 -0.0010 0.000552284667 2.9 -0.001 0 2.9 -0.0010 -0.000552284667 2.9 -0.000552284667 -0.0010 2.9 0.0000 -0.0010 2.9 0.000552284667 -0.0010 2.9 0.0010 -0.000552284667 2.9 0.0010 0.0000 2.9 ] + +AttributeEnd + +WorldEnd + diff --git a/share/tests/hl/highlight.scheme b/share/tests/hl/highlight.scheme new file mode 100644 index 0000000..08c7351 --- /dev/null +++ b/share/tests/hl/highlight.scheme @@ -0,0 +1,186 @@ +; This is a test file to test kates scheme highlighting +; This is a comment + +;; Another comment, usually used. +;BEGIN region marker +;; a vektor +#(1 2 3 4 5) +;END region marker +;; this represents integer 28 (FIXME: does not work perfectly atm!) +28 028 #e28 #i28 ;; Normal, normal, exact, inexact +#b11100 #o34 #d28 #x1c ;; Bin, okt, dec, hex +#oe34 #eo34 ;; combined. + +;; char. +(#\y #\space) ;; list: `y' space. +(#\ #\\ #\)) ;; list of spaces, backslash and`)'. +#\newline ;; a newline-char +#\NewLine ;; another one :) + +"Hello, world" ;; a string + +"hoho, what do you +want to do ;; this is NO comment +with that?" + +;; R5RS definiert diese beiden. +"Das ist \"in Anführungszeichen\" und mit \\ Backslash." + +(let ((x (+ 1 2)) (y "blah")) ;; `let' highlighting. + (and (number? x) ;; `and' highlighting. + (string? y))) + +(let* ((x 2) (y (+ x 1))) ;; `let*' too. + (or (negative? x) ;; `or' anyways. + (negative? y))) + +(do ((vec (make-vector 5)) ;; `do' you may guess! + (i 0 (+ i 1))) + ((= i 5) vec) + (vector-set! vec i i)) + +(quasiquote ((+ 1 2) (unquote (+ 1 2)))) +;; same as: `((+ 1 2) ,(+ 1 2)) + +;; see above. +(quasiquote ((+ 1 2) (unquote-splicing (list 1 2 3)))) +;; same as: `((+ 1 2) ,@(+ 1 2)) + +;; not necessary. +(quote ()) + +(cond ((string? x) (string->symbol x)) ;; `cond' highlighting. + ((symbol? x) => (lambda (x) x)) ;; `=>' highlighting. + (else ;; `else' highlighting. + (error "Blah"))) + +(case x ;; `case' highlighting. + ((#t) 'true) ((#f) 'false) + ((()) 'null) + ((0) 'zero)) + +;; highlight `let-syntax' and `syntax-rules' . +(let-syntax ((when (syntax-rules () + ((when test stmt1 stmt2 ...) + ;; hl `begin' . + (if test (begin stmt1 stmt2 ...)))))) + (let ((if #t)) ;; here`if' is actually no keyword. + (when if (set! if 'now)) ;; nor here. + if)) + +(letrec-syntax ...) ;; hl `letrec-syntax'. + +(define-syntax when + (syntax-rules () + ((when test stmt1 stmt2 ...) + (if test (begin stmt1 stmt2 ...)))))) + +;; variable definitions. +(define natural-numbers ;; hl `define' and the var name + ;; endless stream of all natual numbers. + (letrec ((next-cell ;; hl `letrec'. + (lambda (x) ;; hl `lambda'. + ;; hl `delay' . + (cons x (delay (next-cell (+ x 1))))))) + (next-cell 0))) + +;; a procedure with unusual but allowed name. +(define 1+ + (lambda (x) + (+ x 1))) + +;; a predicate +(define between? + (lambda (x y z) + (if (and (>= x y) (<= x z)) + #t ;; True + #f))) ;; False. + +;; imperative procedure +(define set-something! + (lambda (required-argument another-one . all-remaining-args) + (set-car! another-one (lambda all-args + (set-cdr! required-argument + (append all-remaining-args + all-args)))))) + +(define compose + (lambda (f g) + (lambda (x) + (f (g x))))) + +;; syntactical sugar for procedure-definitions. +(define (compose f g) + (lambda (x) + (f (g x)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; NOW: Guile extensions ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; procedure-generator. +(define ((compose f g) x) + (f (g x))) + +;; scheme doesn't say, which chars may be in variables... +;; At least: Guile accepts umlauts +(define-private (timetr??? sprache) ;; hl `define-private'. + (list-dialekt? sprache)) + +(define-public x #t) ;; hl `define-public'. +(define-module (foo bar)) ;; hl `define-module'. +(define-macro (neither . exprs) ;; hl `define-macro'. + `(and ,@(map (lambda (x) `(not ,x)) exprs))) + +(defmacro neither exprs ;; `defmacro' as well. + `(and ,@(map (lambda (x) `(not ,x)) exprs))) + +;; hl, but I really don't know what this is supposed to do :-) +(define-syntax-macro ...) + +;; hl GOOPS-`defines' +(define-method (foo bar (baz ) qux) ...) +(define-class ...) +(define-generic foo) +(define-accessor bar) + +;; Keywords! +(blah #:foo 33 #:bar 44) + +;; another convention for symbols: +#{foo}# + +#{a +few +lines}# + +#{4711}# + +;; more chars. +#\nul #\nl #\esc #\bs #\bel #\syn #\ack #\sp ;; etc, utc, itc, oops (this is boring) + +#! + guile block-comment. +!# + +;; now, a bit hairy: +#! comment !# +still comment!!! +!# +'now-no-comment-anymore + +;; more precise: +#! comment !# +still comment +!# still comment! +!# +'now-no-comment-anymore + +(while (> foo 10) ;; Highlight `while'. + (set! foo (- foo 1)) + (catch #t ;; Highlight `catch'. + (lambda () (display foo)) + (lambda (key . args) + (if (eq? key 'system-error) + (break) ;; Highlight `break'. + (continue))))) ;; Highlight `continue'. \ No newline at end of file diff --git a/share/tests/hl/highlight.sed b/share/tests/hl/highlight.sed new file mode 100644 index 0000000..464ebd1 --- /dev/null +++ b/share/tests/hl/highlight.sed @@ -0,0 +1,80 @@ +# addresses +123d +/rege[xX] ad\/dress/p +\dother \delimitersdn +$D + +# ranges +/12/,452n +23~4P +2,$H +78,109F + +# negations +/not this line/!h +123,456!g +$!= + +# negation of addresses and ranges +/do not replace this line/!G +/blah/,123!x +/begin/,/end/!v +674~12z + +# the s command +s/hello/world/6gw/output/file +saw\(it\)h \anotheradelim\1era + +# the y command +y/a\nbc/wxyz/ +yxabcx\xyzx + +# the a, i and c commands +a\ +This is literal text\ +That is spread over multiple lines\ +and even contains \\ escaped backslashes + +i\ +The i... + +c\ +... and c commands work similarly + +# labels +:label +blabel +tlabel +Tlabel + +# the w and r commands +w/output/file +W/another/output/file +r/input/file +R/another/output/file + +/the end/q 2 + +# compound commands +/begin/,/end/{ + l 67 + /test/x + y/abc/xyz/ +} + +# semicolons +L 23;x +x;/[Aa]bc/H;$g + +# invalid command +/123/k + +# excess characters +hblah + +# missing line continuation +a +hello world + +# invalid flags +s/hello/world/o diff --git a/share/tests/hl/highlight.sh b/share/tests/hl/highlight.sh new file mode 100644 index 0000000..a354757 --- /dev/null +++ b/share/tests/hl/highlight.sh @@ -0,0 +1,207 @@ +#! /bin/sh +# This is a test script for the Katepart Bash Syntax Highlighting by +# Wilbert Berendsen. This is not runnable !!! + + +# The highlighting recognizes basic types of input, and has a few special cases that +# are all in FindCommands. The main objective is to create really proper nesting of +# (multiline) strings, variables, expressions, etc. + + + +# ============== Tests: =============== + +# basic types: +echo 'single quoted string' +echo "double quoted string" +echo $'string with esc\apes\x0din it' +echo $"string meant to be translated" + + +# comments: +# this is a comment +#this too +echo this is#nt a comment +dcop kate EditInterface#1 #this is + + +# brace expansion +mv my_file.{JPG,jpg} + + +# special characters are escaped: +echo \(output\) \&\| \> \< \" \' \* + + +# variable substitution: +echo $filename.ext +echo $filename_ext +echo ${filename}_ext +echo text${array[$subscript]}.text +echo text${array["string"]}.text +echo ${!prefix*} +echo ${!redir} +echo short are $_, $$, $?, ${@}, etc. +echo ${variable/a/d} +echo ${1:-default} + + +# expression subst: +echo $(( cd << ed + 1 )) + + +# command subst: +echo $(ls -l) +echo `cat myfile` + + +# file subst: +echo $(<$filename) +echo $( my_file.txt 2>&1 + + +# All substitutions also work in strings: +echo "subst ${in}side string" 'not $inside this ofcourse' +echo "The result is $(( $a + $b )). Thanks!" +echo "Your homedir contains `ls $HOME |wc -l` files." + + +# Escapes in strings: +p="String \` with \$ escapes \" "; + + +# keywords are black, builtins dark purple and common commands lighter purple +set +exit +login + + +# Other colorings: +error() { + cat /usr/bin/lesspipe.sh + runscript >& redir.bak + exec 3>&4 +} + + +# do - done make code blocks +while [ $p -lt $q ] +do + chown 0644 $file.$p +done + + +# braces as well +run_prog | sort -u | +{ + echo Header + while read a b d + do + echo $a/$b/$c + done + echo Footer +} + + +# Any constructions can be nested: +echo "A long string with $( + if [ $count -gt 100 ] ; then + echo "much" + else + echo "not much" + fi ) substitutions." ; + + +# Even the case construct is correctly folded: +test -f blaat && +( do_something + case $p in + *bak) + do_bak $p + ;; + *) + dont_bak $p + ;; + esac +) # despite the extra parentheses in the case construction. + + +# variable assignments: +DIR=/dev +p=`ls` +LC_ALL="nl" dcop 'kate*' +_VAR=val +ARR=(this is an array) +ARR2=([this]=too [and]="this too") +usage="$0 -- version $VERSION +Multiple lines of output +can be possible." +ANSWER=yes # here 'yes' isn't highlighed as command + + +# Some commands expect variable names, these are colored correctly: +export PATH=/my/bin:$PATH BLAAT +export A B D +local p=3 x y='\' +read x y z <<< $hallo +unset B +declare -a VAR1 VAR2 && exit +declare less a && b + +# options are recoqnized: +zip -f=file.zip +./configure --destdir=/usr +make destdir=/usr/ + + +# [[ and [ correctly need spaces to be regarded as structure, +# otherwise they are patterns (currently treated as normal text) +if [ "$p" == "" ] ; then + ls /usr/bin/[a-z]* +elif [[ $p == 0 ]] ; then + ls /usr/share/$p +fi + +# Fixed: +ls a[ab]* # dont try to interprete as assignment with subscript (fixed) +a[ab] +a[ab]=sa + + +# Here documents are difficult to catch: +cat > myfile << __EOF__ +You're right, this is definitely no bash code +But ls more $parameters should be expanded. +__EOF__ + + +# quoted: +cat << "EOF" | egrep "this" >&4 # the rest of the line is still considered bash source +You're right, this is definitely no bash code +But ls more $parameters should be expanded. :-> +EOF + + +# indented: +if true +then + cat <<- EOF + Indented text with a $dollar or \$two + EOF +elif [ -d $file ]; then + cat <<- "EOF" + Indented text without a $dollar + EOF +fi + + +case 1 in +2) echo xxx; +;; +1) echo yyy; +esac + +ls #should be outside of case 1 folding block \ No newline at end of file diff --git a/share/tests/hl/highlight.sp b/share/tests/hl/highlight.sp new file mode 100644 index 0000000..046dfea --- /dev/null +++ b/share/tests/hl/highlight.sp @@ -0,0 +1,32 @@ +*current sink p-type inverter - dc sweep of voltage I/O +*file:invcsp0.sp + +*parameters +.PARAM ww=38.5 $ parameter for width which will be swept + +*circuit net list +Vdd vdd GND dc 5.0 +Vbias bias GND dc 2.5 +Vin src GND dc 0.0 +Mn out bias GND GND nmosl1 W=16 L=8 +Mp out in vdd vdd pmosl1 W=ww L=8 +Cl out GND 0.01P +Rs src in 10K + +*options & analysis +.OPTIONS POST=2 SCALE=1U $ output results for plot; scale mosfet L & W dimensions +.DC Vin 0 5 0.1 $sweep I/P voltage +.MEASURE DC vin_bal WHEN V(out)=2.5 + +*output +.plot DC v(src) v(in) v(out) + +*mosfet models - level 1 +.INC 'l1typ.inc' + +$ a comment +* another comment + +.END + + diff --git a/share/tests/hl/highlight.spec b/share/tests/hl/highlight.spec new file mode 100644 index 0000000..65c70a0 --- /dev/null +++ b/share/tests/hl/highlight.spec @@ -0,0 +1,775 @@ +# +# spec file for package kdevelop +# +# Copyright (c) 2008 SUSE LINUX Products GmbH, Nuernberg, Germany. +# This file and all modifications and additions to the pristine +# package are under the same license as the package itself. +# +# Copyright (c) 2007-2008 Amilcar Lucas +# Copyright (c) 2003-2006 Than Ngo +# Copyright (c) 2002-2006 Laurent Montel +# +# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# + +# norootforbuild + +######################################################################################### +# Commom part +######################################################################################### +%define branch_source_date 20081218 +%define kdevelop_version 3.5.4 +%define kde_version 3.4.0 +%define qt_version 3.3.2 + +%if 0%{?suse_version} != 0 +%define name kdevelop3 +%else +%define name kdevelop +%endif +Name: %{name} +URL: http://www.kdevelop.org/ +Version: %{kdevelop_version} +Release: 1 +Summary: Integrated Development Environment for the X Window System, Qt, KDE, and GNOME +License: GPL (GNU General Public License) +Group: Development/Tools/IDE +Provides: kdevelop +Obsoletes: kdevelop +Obsoletes: gideon +Obsoletes: kdevelop2 +#Autoreqprov: on +Source: http://download.kde.org/download.php?url=stable/3.5.10/kdevelop-%{version}.tar.bz2 +#Source1: ftp://129.187.206.68/pub/unix/ide/KDevelop/c_cpp_reference-2.0.2_for_KDE_3.2.tar.bz2 +%if 0%{?mandriva_version} +Source2: kdevelop-3.0-Makefile.PL +Epoch: 3 +%endif +%if 0%{?fedora_version} +Epoch: 9 +Obsoletes: kdevelop-c_c++_ref +#Patch1: c_cpp_reference-2.0.2-config.patch +#Patch2: kde-libtool.patch +%endif +BuildRoot: %{_tmppath}/%{name}-%{version}-build +Packager: Amilcar Lucas + +######################################################################################### +# SuSE, openSUSE +######################################################################################### +%if 0%{?suse_version} + +# it is a qt3 based application +BuildRequires: qt3-devel >= %{qt_version} +# For the entire kdelibs infrastructure +BuildRequires: kdelibs3-devel >= %{kde_version} +%if %suse_version < 1010 +BuildRequires: update-desktop-files +# for the kdevassistant +BuildRequires: qt3-devel-doc >= %{qt_version} +%endif +%if %suse_version < 1000 +BuildRequires: libjpeg-devel +%endif +# for the cvsservice (cvs support) +BuildRequires: kdesdk3-devel >= %{kde_version} +# for the presistent class store (PCS) +BuildRequires: db-devel >= 4.1 +BuildRequires: doxygen +BuildRequires: graphviz >= 1.8.7 +# For the QMake parser +BuildRequires: flex >= 2.5.4 +# for svn support +BuildRequires: subversion-devel +#BuildRequires: apr +%if %suse_version > 1030 +# for the svn-merge functionality provided by subversion 1.5 +BuildRequires: sqlite-devel +%endif +# Nice to have KDE API documentation integrated in KDevelop +Requires: kdelibs3-devel-doc >= %{kde_version} +Requires: kdebase3 >= %{kde_version} +Requires: kdesdk3 >= %{kde_version} +Requires: cvs /usr/bin/make +Requires: perl >= 5.004 +Requires: graphviz >= 1.8.7 +Requires: db >= 4.1 +#For debugging with GDB-MI support +Requires: gdb >= 6.4 +Requires: ctags >= 5 +Requires: libtool >= 1.4 +Requires: qt3-devel-tools >= %{qt_version} + +# ruby templates in there +Requires: kdebindings3-ruby >= %{kde_version} +# python templates in there +Requires: kdebindings3-python >= %{kde_version} +%endif + +######################################################################################### +# Mandriva +######################################################################################### +%if 0%{?mandriva_version} +%define __libtoolize /bin/true + +%define use_enable_final 0 +%{?_no_enable_final: %{expand: %%global use_enable_final 0}} + +%define compile_apidox 0 +%{?_no_apidox: %{expand: %%global compile_apidox 0}} + +%define unstable 0 +%{?_unstable: %{expand: %%global unstable 1}} + +%if %unstable +%define dont_strip 1 +%endif + +%define lib_name_orig libkdevelop +%if 0%{?mandriva_version} < 2008 +%define lib_major 3 +%define lib_name %mklibname kdevelop %lib_major +%endif +%define old_lib_major 2 +%define old_lib_name %mklibname kdevelop %old_lib_major +%if 0%{?mandriva_version} >= 2008 +%define major 3 +%define libname %mklibname kdevelop %{major} +%define develname %mklibname %{name} -d +%endif + +#BuildRequires: libqt3 >= %{qt_version} +BuildRequires: qt3-devel >= %{qt_version} +BuildRequires: kdelibs-devel >= %{kde_version} +BuildRequires: python +BuildRequires: python-devel +BuildRequires: libjpeg-devel +BuildRequires: png-devel +%if 0%{?mandriva_version} <= 2006 +BuildRequires: XFree86-devel +%else +BuildRequires: X11-devel +%endif +# for the kdevassistant +BuildRequires: qt3-static-devel >= %{qt_version} +BuildRequires: libart_lgpl-devel +# For the QMake parser +#BuildRequires: flex >= 2.5.4 +# for the cvsservice +BuildRequires: libkdesdk-cervisia-devel >= %{kde_version} +BuildRequires: graphviz >= 1.8.6 +BuildRequires: qt3-doc >= %{qt_version} +BuildRequires: db-devel >= 4.1 +# for svn support +BuildRequires: subversion-devel +BuildRequires: apr-devel +BuildRequires: apr-util-devel +# doxygen is always required in order to build the parts/doxygen/ subdir +BuildRequires: doxygen +%py_requires -d + +#Requires: enscript +Requires: gcc-c++ +Requires: gcc-cpp +#Requires: arts +#Requires: openssl-devel +#Requires: kdegraphics kdelibs-devel kdesdk kdeutils +Requires: kdelibs-devel-doc >= %{kde_version} +Requires: kdesdk >= %{kde_version} +Requires: kdebase >= %{kde_version} +%if 0%{?mandriva_version} <= 2006 +Requires: XFree86-devel +%else +Requires: libx11-devel +%endif +Requires: jpeg-devel +Requires: qt3 >= %{qt_version} +Requires: make +Requires: perl >= 5.0004 +#Requires: sgml-tools +Requires: gettext +Requires: libz-devel +Requires: ctags >= 5 +Requires: png-devel libart_lgpl-devel +Requires: libtool >= 1.4 +Requires: automake >= 1.6 +Requires: autoconf >= 2.52 +# required by the autoconf/automake projects +Requires: awk +Requires: db >= 4.1 +%if 0%{?mandriva_version} < 2008 +Requires: %lib_name = %epoch:%version-%release +%else +Requires: %{libname} = %epoch:%version-%release +%endif +Requires: kdesdk-cervisia >= %{kde_version} +Requires: doxygen +Requires: graphviz >= 1.8.6 +Requires(post): desktop-file-utils +Requires(postun): desktop-file-utils +Conflicts: mandrake-mime <= 0.4-5mdk +%endif + +######################################################################################### +# Fedora, RHEL or CentOS +######################################################################################### +%if 0%{?fedora_version} || 0%{?rhel_version} || 0%{?centos_version} +%define debug 0 +%define final 0 + +%define qt_epoch 1 +%define kdelibs_epoch 6 + +%define make_cvs 1 + +%define disable_gcc_check_and_hidden_visibility 1 + +Requires(post): /sbin/ldconfig +Requires(postun): /sbin/ldconfig +Requires: kdelibs-devel >= %{kdelibs_epoch}:%{kde_version} +Requires: kdesdk >= %{kde_version} +Requires: make +Requires: perl >= 0:5.004 +Requires: libtool >= 1.4 +#Requires: flex >= 2.5.4 +Requires: qt-designer >= %{qt_epoch}:%{qt_version} +Requires: db4 >= 4.1 + +BuildRequires: autoconf +BuildRequires: automake +BuildRequires: libtool +%if 0%{?fedora_version} > 8 +BuildRequires: kdelibs3-devel >= %{kde_version} +%else +BuildRequires: kdelibs-devel >= %{kde_version} +%endif +BuildRequires: gcc-c++ +%if 0%{?fedora_version} > 8 +BuildRequires: qt3 +BuildRequires: qt3-devel >= %{qt_version} +BuildRequires: kdelibs3-devel >= %{kde_version} +%else +BuildRequires: qt +BuildRequires: qt-devel >= %{qt_version} +BuildRequires: kdelibs-devel >= %{kde_version} +%endif +BuildRequires: db4-devel >= 4.1 +%if 0%{?rhel_version} != 406 +BuildRequires: kdesdk-devel >= %{kde_version} +%endif +BuildRequires: doxygen +# Both RHEL and CentOS do not provide graphviz +%if 0%{?fedora_version} +BuildRequires: graphviz >= 1.8.6 +%endif +# For the QMake parser +BuildRequires: flex >= 2.5.4 +%if 0%{?rhel_version} != 406 +# for svn support +BuildRequires: subversion-devel >= 1.3 +BuildRequires: apr-devel +BuildRequires: neon-devel +%endif +%endif + +%description +An integrated development environment (IDE) that allows you to write +programs for the X Window System, the Qt library, or KDE. It includes a +documentation browser, a source code editor with syntax highlighting, a +GUI for the compiler, and much more. + + + +Authors: +-------- + Andreas Pakulat + Robert Gruber + Jens Dagerbo + Alexander Dymo + Vladimir Prus + Matt Rogers + Megan Webb + Richard Dale + Anne-Marie Mahfouf + Amilcar do Carmo Lucas + David Nolden + Jonas Jacobi + Stephan Binner + Andras Mantia + Oliver Kellogg + + +######################################################################################### +# SUSE +######################################################################################### +%if 0%{?suse_version} +%prep +%setup -q -n kdevelop-%{version} +#%patch0 +#%patch1 +#%patch2 +#%patch4 +# source the standard build environment as defined in kdelibs3 package +. /etc/opt/kde3/common_options +# replace the admin/ folder with the version from kdelibs3 (will work for sure with +# current autoconf and automake) and create Makefile.in and configure script. +update_admin --no-unsermake --no-final + +%build +. /etc/opt/kde3/common_options +export CFLAGS="-fno-strict-aliasing $CFLAGS" +./configure $configkde \ + --with-kdelibsdoxy-dir=/opt/kde3/share/doc/HTML/en/kdelibs-apidocs \ + --with-pythondir=%_libdir/python \ + --with-qtdoc-dir=/usr/%_lib/qt3/doc/html \ +%if %suse_version < 1010 + --disable-subversion \ +%endif + --disable-final +do_make %{?jobs:-j %jobs} + +%install +. /etc/opt/kde3/common_options +make DESTDIR=${RPM_BUILD_ROOT} $INSTALL_TARGET +# use our admin tar ball (commented out because KDevelop already uses an updated admin/ ) +#tar cfvz ${RPM_BUILD_ROOT}/opt/kde3/share/apps/kdevappwizard/template-common/admin.tar.gz admin +%suse_update_desktop_file kdevelop Development IDE +%suse_update_desktop_file kdevelop_c_cpp Development IDE +%suse_update_desktop_file kdevelop_kde_cpp Development IDE +%suse_update_desktop_file kdevelop_ruby Development IDE +%suse_update_desktop_file kdevelop_scripting Development IDE +%suse_update_desktop_file kdevassistant Development Documentation +%suse_update_desktop_file kdevdesigner Development GUIDesigner +%find_lang kdevelop +rm -rf $RPM_BUILD_ROOT/opt/kde3/kdevbdb/docs/CVS +kde_post_install + +%clean +rm -rf $RPM_BUILD_ROOT + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +# the -devel package +%package devel +Group: Development/Tools/IDE +Summary: Integrated Development Environment: Build Environment +Requires: kdevelop3 = %version + +%description devel +Development files to develop KDevelop itself. KDevelop is an integrated +development environment (IDE) that allows you to write +programs for the X Window System, the Qt library, or KDE. It includes a +documentation browser, a source code editor with syntax highlighting, a +GUI for the compiler, and much more. + + +%files devel +%defattr(-,root,root) +/opt/kde3/include/* +/opt/kde3/%_lib/libprofileengine.so +/opt/kde3/%_lib/liblang_interfaces.so +/opt/kde3/%_lib/liblang_debugger.so +/opt/kde3/%_lib/libkinterfacedesigner.so +/opt/kde3/%_lib/libkdevwidgets.so +/opt/kde3/%_lib/libkdevshell.so +/opt/kde3/%_lib/libkdevqmakeparser.so +/opt/kde3/%_lib/libkdevpropertyeditor.so +/opt/kde3/%_lib/libkdevextras.so +/opt/kde3/%_lib/libkdevelop.so +/opt/kde3/%_lib/libkdevcppparser.so +/opt/kde3/%_lib/libkdevcatalog.so +/opt/kde3/%_lib/libkdevbuildtoolswidgets.so +/opt/kde3/%_lib/libkdevbuildbase.so +/opt/kde3/%_lib/libgdbmi_parser.so +/opt/kde3/%_lib/libdocumentation_interfaces.so +/opt/kde3/%_lib/libdesignerintegration.so +/opt/kde3/%_lib/libd.so +/opt/kde3/%_lib/libd.la +/opt/kde3/%_lib/libdesignerintegration.la +/opt/kde3/%_lib/libdocumentation_interfaces.la +/opt/kde3/%_lib/libgdbmi_parser.la +/opt/kde3/%_lib/libkdevbuildbase.la +/opt/kde3/%_lib/libkdevbuildtoolswidgets.la +/opt/kde3/%_lib/libkdevcatalog.la +/opt/kde3/%_lib/libkdevcppparser.la +/opt/kde3/%_lib/libkdevelop.la +/opt/kde3/%_lib/libkdevextras.la +/opt/kde3/%_lib/libkdevpropertyeditor.la +/opt/kde3/%_lib/libkdevqmakeparser.la +/opt/kde3/%_lib/libkdevshell.la +/opt/kde3/%_lib/libkdevwidgets.la +/opt/kde3/%_lib/libkinterfacedesigner.la +/opt/kde3/%_lib/liblang_debugger.la +/opt/kde3/%_lib/liblang_interfaces.la +/opt/kde3/%_lib/libprofileengine.la + +%files -f kdevelop.lang +%defattr(-,root,root) +%dir /opt/kde3/share/desktop-directories +%doc /opt/kde3/share/doc/HTML/en/kde_app_devel +%doc /opt/kde3/share/doc/HTML/en/kdevelop-apidocs +/opt/kde3/share/applications/kde/* +/opt/kde3/share/apps/* +%config /opt/kde3/share/config/* +/opt/kde3/share/icons/??color +/opt/kde3/bin/* +%dir /opt/kde3/%_lib/kconf_update_bin +/opt/kde3/%_lib/kconf_update_bin/kdev-gen-settings-kconf_update +/opt/kde3/%_lib/kde3/kded_kdevsvnd.so +/opt/kde3/%_lib/kde3/kio_chm.so +/opt/kde3/%_lib/kde3/kio_csharpdoc.so +/opt/kde3/%_lib/kde3/kio_kdevsvn.so +/opt/kde3/%_lib/kde3/kio_perldoc.so +/opt/kde3/%_lib/kde3/kio_pydoc.so +/opt/kde3/%_lib/kde3/libclearcaseintegrator.so +/opt/kde3/%_lib/kde3/libcvsserviceintegrator.so +/opt/kde3/%_lib/kde3/libdocchmplugin.so +/opt/kde3/%_lib/kde3/libdoccustomplugin.so +/opt/kde3/%_lib/kde3/libdocdevhelpplugin.so +/opt/kde3/%_lib/kde3/libdocdoxygenplugin.so +/opt/kde3/%_lib/kde3/libdockdevtocplugin.so +/opt/kde3/%_lib/kde3/libdocqtplugin.so +/opt/kde3/%_lib/kde3/libkchmpart.so +/opt/kde3/%_lib/kde3/libkdev*.so +/opt/kde3/%_lib/kde3/libperforceintegrator.so +/opt/kde3/%_lib/kde3/libsubversionintegrator.so +/opt/kde3/%_lib/kde3/kded_kdevsvnd.la +/opt/kde3/%_lib/kde3/kio_chm.la +/opt/kde3/%_lib/kde3/kio_csharpdoc.la +/opt/kde3/%_lib/kde3/kio_kdevsvn.la +/opt/kde3/%_lib/kde3/kio_perldoc.la +/opt/kde3/%_lib/kde3/kio_pydoc.la +/opt/kde3/%_lib/kde3/libclearcaseintegrator.la +/opt/kde3/%_lib/kde3/libcvsserviceintegrator.la +/opt/kde3/%_lib/kde3/libdocchmplugin.la +/opt/kde3/%_lib/kde3/libdoccustomplugin.la +/opt/kde3/%_lib/kde3/libdocdevhelpplugin.la +/opt/kde3/%_lib/kde3/libdocdoxygenplugin.la +/opt/kde3/%_lib/kde3/libdockdevtocplugin.la +/opt/kde3/%_lib/kde3/libdocqtplugin.la +/opt/kde3/%_lib/kde3/libkchmpart.la +/opt/kde3/%_lib/kde3/libkdev*.la +/opt/kde3/%_lib/kde3/libperforceintegrator.la +/opt/kde3/%_lib/kde3/libsubversionintegrator.la +/opt/kde3/%_lib/libprofileengine.so.* +/opt/kde3/%_lib/liblang_interfaces.so.* +/opt/kde3/%_lib/liblang_debugger.so.* +/opt/kde3/%_lib/libkinterfacedesigner.so.* +/opt/kde3/%_lib/libkdevwidgets.so.* +/opt/kde3/%_lib/libkdevshell.so.* +/opt/kde3/%_lib/libkdevqmakeparser.so.* +/opt/kde3/%_lib/libkdevpropertyeditor.so.* +/opt/kde3/%_lib/libkdevextras.so.* +/opt/kde3/%_lib/libkdevelop.so.* +/opt/kde3/%_lib/libkdevcppparser.so.* +/opt/kde3/%_lib/libkdevcatalog.so.* +/opt/kde3/%_lib/libkdevbuildtoolswidgets.so.* +/opt/kde3/%_lib/libkdevbuildbase.so.* +/opt/kde3/%_lib/libgdbmi_parser.so.* +/opt/kde3/%_lib/libdocumentation_interfaces.so.* +/opt/kde3/%_lib/libdesignerintegration.so.* +/opt/kde3/%_lib/libd.so.* +/opt/kde3/share/desktop-directories/kde-development-kdevelop.directory +/opt/kde3/share/mimelnk/*/*.desktop +/opt/kde3/share/services/* +/opt/kde3/share/servicetypes/* +%endif + + + +######################################################################################### +# Mandriva +######################################################################################### +%if 0%{?mandriva_version} + +%post +%update_menus +%if 0%{?mandriva_version} > 2006 +%{update_desktop_database} +%update_icon_cache crystalsvg +%endif + + +%postun +%clean_menus +%if 0%{?mandriva_version} > 2006 +%{clean_desktop_database} +%clean_icon_cache crystalsvg +%endif + +%files +%defattr(-,root,root) +%_bindir/* +%_datadir/applications/kde/* +%_libdir/kde3/* +%_datadir/apps/* +%_datadir/desktop-directories/kde-development-kdevelop.directory +%_datadir/icons/*/*/*/* +%_datadir/config/kdeveloprc +%_datadir/mimelnk/*/*.desktop +%_datadir/services/* +%_datadir/servicetypes/* +%if 0%{?mandriva_version} < 2008 +%_menudir/* +%endif +%_libdir/kconf_update_bin/kdev-gen-settings-kconf_update +%_datadir/config/kdevassistantrc + +#------------------------------------------------ + +%if 0%{?mandriva_version} < 2008 +%package -n %lib_name-devel +%else +%package -n %{develname} +%endif +Summary: Development files for kdevelop +Group: Development/KDE and Qt + +Obsoletes: kdevelop-devel, %old_lib_name-devel +Provides: kdevelop-devel = %epoch:%version-%release +%if 0%{?mandriva_version} < 2008 +Requires: %lib_name = %epoch:%version-%release +%else +Requires: %{libname} = %epoch:%version-%release +Obsoletes: %mklibname %{name} 3 -d +%endif + +%if 0%{?mandriva_version} < 2008 +%description -n %lib_name-devel +%else +%description -n %{develname} +%endif +Development files for kdevelop. + +%if 0%{?mandriva_version} < 2008 +%files -n %lib_name-devel +%else +%files -n %{develname} +%endif +%defattr(-,root,root) +%_libdir/*.so +%dir %_includedir/kdevelop +%dir %_includedir/kinterfacedesigner +%_includedir/*/* + +#------------------------------------------------ + +%if 0%{?mandriva_version} < 2008 +%package -n %lib_name +%else +%package -n %{libname} +%endif +Summary: Libraries files for kdevelop +Group: Development/KDE and Qt +Obsoletes: %old_lib_name +%if 0%{?mandriva_version} < 2008 +Provides: %lib_name_orig = %epoch:%version-%release + +%description -n %lib_name +Libraries files for kdevelop. + +%post -n %lib_name-devel -p /sbin/ldconfig +%postun -n %lib_name-devel -p /sbin/ldconfig + +%post -n %lib_name -p /sbin/ldconfig +%postun -n %lib_name -p /sbin/ldconfig + +%files -n %lib_name +%else +Provides: %{libname}_orig = %epoch:%version-%release + +%description -n %{libname} +Libraries files for kdevelop. + +%post -n %{develname} -p /sbin/ldconfig +%postun -n %{develname} -p /sbin/ldconfig + +%post -n %{libname} -p /sbin/ldconfig +%postun -n %{libname} -p /sbin/ldconfig + +%files -n %{libname} +%endif +%defattr(-,root,root) +%_libdir/*.la +%_libdir/*.so.* + + +#------------------------------------------------ + +%package doc +Summary: Development files for kdevelop +Group: Development/KDE and Qt + +%description doc +Documentation kdevelop. + +%files doc +%defattr(-,root,root) +%dir %_docdir/HTML/en/kdevelop +%_docdir/HTML/en/kdevelop/* +%dir %_docdir/HTML/en/kde_app_devel +%_docdir/HTML/en/kde_app_devel/* +%doc %_docdir/HTML/en/kdevelop-apidocs + +#------------------------------------------------ + +%prep +%setup -q + +%build +%if 0%{?mandriva_version} < 2008 +export QTDIR=%_prefix/lib/qt3 +%else +export QTDIR=%{qt3dir} +%endif +QTDOCDIR=%_defaultdocdir/qt-*/doc/html + +%configure2_5x \ +%if %unstable + --enable-debug=full \ +%else + --disable-debug \ +%endif +%if %use_enable_final + --enable-final \ +%endif + --disable-static \ + --disable-embedded \ + --disable-palmtop \ + --disable-rpath \ +%if "%{_lib}" != "lib" + --enable-libsuffix="%(A=%{_lib}; echo ${A/lib/})" \ +%endif + --with-pic \ + --with-qtdoc-dir=$QTDOCDIR \ + --enable-scripting \ +%if 0%{?mandriva_version} < 2005 + --disable-subversion \ +%endif + --with-apr-config=%_bindir/apr-1-config \ + --with-apu-config=%_bindir/apu-1-config \ + --with-kdelibsdoc-dir=%_docdir/HTML/en/ + +%make +%if %compile_apidox +make apidox +%endif + +%install +rm -fr %buildroot + +#### #### +#### Convert KDE menu structure to Mandriva menu structure #### +#### #### + +%makeinstall_std + +%if 0%{?mandriva_version} < 2008 +# Create LMDK menus +install -d %buildroot/%_datadir/applications/kde/ + +#Create LMDK menu entries +install -d %buildroot/%_menudir/ +for kdev in kdevelop kdevdesigner kdevassistant kdevelop_c_cpp kdevelop_kde_cpp kdevelop_ruby kdevelop_scripting; do + kdedesktop2mdkmenu.pl kdevelop "More Applications/Development/Development Environments" %buildroot/%_datadir/applications/kde/${kdev}.desktop %buildroot/%_menudir/kdevelop-${kdev} +done +%else +( +cd %{buildroot}/%name-%version/ +rm -rf perl-kdevelop +mkdir perl-kdevelop/ +cd perl-kdevelop/ +install -m 0755 %SOURCE2 Makefile.PL +ln ../parts/appwizard/common/kdevelop.pm kdevelop.pm +perl Makefile.PL INSTALLDIRS=vendor +make install DESTDIR=%buildroot +) +%endif + +%clean +rm -fr %buildroot +%endif + + + +######################################################################################### +# Fedora, RHEL or CentOS +######################################################################################### +%if 0%{?fedora_version} || 0%{?rhel_version} || 0%{?centos_version} +%prep + +%setup -q +#%setup -q -a1 + +%build +export KDEDIR=%{_prefix} +%if 0%{?fedora_version} >= 5 +QTDIR="" && source "%{_sysconfdir}/profile.d/qt.sh" +%else +QTDIR="" && source /etc/profile.d/qt.sh +%endif +export FLAGS="$RPM_OPT_FLAGS" +# c references +#pushd c_cpp_reference-2.0.2_for_KDE_3.2 +#%configure \ +# --with-qt-libraries=$QTDIR/lib \ +# --with-qt-includes=$QTDIR/include \ +# --with-extra-libs=%{_libdir} +#popd +%configure \ + --enable-new-ldflags \ + --disable-dependency-tracking \ +%if %{disable_gcc_check_and_hidden_visibility} + --disable-gcc-hidden-visibility \ +%endif + --disable-rpath \ +%if %{debug} == 0 + --disable-debug \ + --disable-warnings \ +%endif +%if %{final} + --enable-final \ +%endif + --with-qtdoc-dir=%{_docdir}/qt-devel-%{qt_version}/html/ \ + --with-kdelibsdoc-dir=%{_docdir}/HTML/en/kdelibs-apidocs/ \ + --with-qt-libraries=$QTDIR/lib \ + --with-extra-libs=%{_libdir} +make %{?_smp_mflags} + +%install +rm -rf $RPM_BUILD_ROOT + +make DESTDIR=$RPM_BUILD_ROOT install +#make -C c_cpp_reference-2.0.2_for_KDE_3.2 DESTDIR=$RPM_BUILD_ROOT install + +# remove useless files +rm -rf $RPM_BUILD_ROOT%{_prefix}/kdevbdb + +%post -p /sbin/ldconfig + +%postun -p /sbin/ldconfig + +%clean +rm -rf $RPM_BUILD_ROOT + +%files +%defattr(-,root,root) +%doc %{_docdir}/HTML/en/* +%{_bindir}/* +%{_libdir}/kde3/* +%{_libdir}/lib* +%{_libdir}/kconf_update_bin/* +%{_includedir}/* +%{_datadir}/applications/kde/* +%{_datadir}/apps/* +%config %{_datadir}/config/* +%{_datadir}/desktop-directories/* +%{_datadir}/icons/*/*/*/* +%{_datadir}/mimelnk/application/* +%{_datadir}/mimelnk/text/* +%{_datadir}/services/* +%{_datadir}/servicetypes/* +%endif + diff --git a/share/tests/hl/highlight.t2t b/share/tests/hl/highlight.t2t new file mode 100644 index 0000000..5b5f379 --- /dev/null +++ b/share/tests/hl/highlight.t2t @@ -0,0 +1,90 @@ +txt2tags sample + + +%!--includeconf: config.t2t +% disabled here because there is no external file +%!preproc: 'JUST A TEST' ' ' +%!postproc: '(?i)()' ' shots\1' + +%!--include: menu.t2t + += Title 1 = + + +== My Subtitle 1 ==[some definition] + +Some examples: + +- A paragraph with **bold**, //italic// and --strike--. +- You can even __underline your docs__! + +- And use **//bold and italic//** +- or //**italic and bold**// + +Here is a nice pic: [img/t2tpowered.png]. + +- And a [link to a cool website http://txt2tags.sf.net]! + +- A table : + + || Name | Age | Gender | + | John | 33 | Male | + | Mary | 19 | Female | + + +``` A verbatim line + +And it's working for ``special code`` like this. + +``` +Unfortunately I can't color this verbatim content yet. +``` + + +== My Subtitle 2 == + + +Lorem ipsum etc +Lorem ipsum etc Lorem ipsum etc + +- Test d'écriture avec des accents à la française. Ça marche ou pas ? + +== My Subtitle 3 == + + +Lorem ipsum etc +Lorem ipsum etc + +Here is a direct link: http://kde.org + + +- Another boring part... + + + +=== My Subsubtitle 1 === + +//It's a level 3 header// + +- list 1 +- list 2 + - list 2b +- list 3 + + +=== My Subsubtitle 2 === + +//It's another level 3 header// + ++ ordered list 1 ++ list 2 + + list 2B + + list 2C ++ list 3 + + +== My Subtitle 4 == + +nothing to say here... + diff --git a/share/tests/hl/highlight.tcl b/share/tests/hl/highlight.tcl new file mode 100644 index 0000000..d6b7276 --- /dev/null +++ b/share/tests/hl/highlight.tcl @@ -0,0 +1,50 @@ +# tcl syntax highlighting sample script for Kate +# +# author: JM. Philippe 15/03/04 + +# escaped characters +set String \{ +set String \{ +set String \" +set String " \" " +set String " \{ " + +#comments and not comments +# is comments +;#is comments + # is comments +#

is html comment

+puts ok; # is comments +set String [string map { {»is not comments}} $String] +set String \#not_a_comment + +# blocks +proc test {arg1 {arg2 {}} {arg3 {fr fq r}}} { + if {1} {; #comments + set String \{; # not a block start + } +} + +proc test args { + set String \}; # not a block end +} + +# BEGIN - collapsable comments +# blablabla +# END + +# strings +set String "feqr feqr $gqer gqe" +set String "feqr +feqr \" $gqer \ +gqe +" +set String {feqr +feqr \{ $gqer \ +gqe +} + +# variables +set b+1 [incr b] +set {incr-b} ${b+1} +puts ${incr-b} diff --git a/share/tests/hl/highlight.tex b/share/tests/hl/highlight.tex new file mode 100644 index 0000000..b706f70 --- /dev/null +++ b/share/tests/hl/highlight.tex @@ -0,0 +1,73 @@ +% LaTeX test file for kate's syntax highlighting and code folding + +\ordinaryLaTeXcommandwithoption[10pt,a4paper]{article} +% BEGIN region +%comment, this is all ok % $ +\%no comments please +\\%comment +% END of region + +\newcommand{\nohighlighting} + +\section{normal} + +\ref{blue} +\pageref{blue} +\cite{blue} + +\begin{environmentshavespecialcolors} +normal +\end{environmentshavespecialcolors} + +$equations are green, \commands somewhat darker$ +normal +$$equations are green, \commands somewhat darker$$ +normal +\( +\frac{1}{2} +\begin{test} +\end{test} +\) +normal +\[ +%comment +displaymath +\] +normal +\begin{equation} +green\darkergreen +\begin{test} +\test +\end{test} +\end{equation} + +\begin{equation*} +green\darkergreen +%comment +\begin{test} +\test +\end{test} +\%no comment +\end{equation*} + +\{ %this should be comment + +\verb%this shouldn't be%and this should be normal text + +\begin{verbatim} +text inside a verbatim environment is also treated special $ %, +you can even put a \begin{verbatim} inside +\end{verbatim} + +normal + +\begin{Verbatim} +&@@#^%&^#$ +\end{Verbatim} + + +\begin{Verbatim*} +@*&^#@*(^#(*@& +\end{Verbatim*} + +normal \ No newline at end of file diff --git a/share/tests/hl/highlight.wrl b/share/tests/hl/highlight.wrl new file mode 100644 index 0000000..2fb4b41 --- /dev/null +++ b/share/tests/hl/highlight.wrl @@ -0,0 +1,41 @@ +#VRML V2.0 utf8 +# +# VRML highlighting test for Kate's syntax highlighting +# + +# Keywords +DEF, EXTERNPROTO, FALSE, IS, NULL, PROTO, ROUTE, TO, TRUE, USE, eventIn, +eventOut, exposedField, field + +# Data types +MFColor, MFFloat, MFInt32, MFNode. MFRotation, MFString, MFTime, MFVec2f, +MFVec3f, SFBool, SFColor, SFFloat, SFImage, SFInt32, SFNode, SFRotation, +SFString, SFTime, SFVec2f, SFVec3f + +# Predefined nodes +Anchor, Appearance, AudioClip, Background, Billboard, Box, Collision, Color, +ColorInterpolator, Cone, Coordinate, CoordinateInterpolator, Cylinder, +CylinderSensor, DirectionalLight, ElevationGrid, Extrusion, Fog, FontStyle, +Group, ImageTexture, IndexedFaceSet, IndexedLineSet, Inline, LOD, Material, +MovieTexture, NavigationInfo, Normal, NormalInterpolator, OrientationInterpolator, +PixelTexture, PlaneSensor, PointLight, PointSet, PositionInterpolator, +ProximitySensor, ScalarInterpolator, Script, Shape, Sound, Sphere, SphereSensor, +SpotLight, Switch, Text, TextureCoordinate, TextureTransform, TimeSensor, +TouchSensor, Transform, Viewpoint, VisibilitySensor, WorldInfo + +# Some real VRML constructs to see if highlighting of int, float etc. works +NavigationInfo { + avatarSize [0.25, 1.6, 0.75] + headlight TRUE + speed 1 + type ["WALK", "ANY"] + visibilityLimit 0.0 +} + +# some further testing for strings: linefeeds are allowed within strings +Text { + string ["some special in-string characters: \" \\ + some more text in the next line + and yet another line"] +} + diff --git a/share/tests/hl/highlight.xml b/share/tests/hl/highlight.xml new file mode 100644 index 0000000..007449c --- /dev/null +++ b/share/tests/hl/highlight.xml @@ -0,0 +1,67 @@ + + + + + +This is a pseudo XML file to test Kate's XML syntax highlighting. + +Doctype: + + +Processing instruction: + + +Comments: + + + +Comment inside element: + content + +Markup inside comment: + + +Empty element: + + + +Simple element plus content: + some content + some + content + +Namespace for elements and attributes: + content + content + +Elements containing allowed characters: + + + +Elements containing allowed start characters: + <:element foo="test"/> + <_element foo="test"/> + +Single quotes (the same as double quotes): + content + +Allowed Whitespace: + + content + +Entities: +   + å + å + å + И + 水 + + +Illegal XML, should not be highlighted: + <0foobar> -- no digit as first character + <-foo> -- no dash as first character diff --git a/share/tests/hl/highlight.xsl b/share/tests/hl/highlight.xsl new file mode 100644 index 0000000..f6e0efb --- /dev/null +++ b/share/tests/hl/highlight.xsl @@ -0,0 +1,109 @@ + + + + + + + + + +Linux at Home Links + + + + <xsl:value-of select="h:a/h:strong"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <xsl:value-of select="normalize-space($title)"/> + + + + + + + + + diff --git a/share/tests/hl/highlight.y b/share/tests/hl/highlight.y new file mode 100644 index 0000000..f7715e6 --- /dev/null +++ b/share/tests/hl/highlight.y @@ -0,0 +1,54 @@ +/* Yacc / Bison hl test file. + * It won't compile :-) Sure ! + */ + +%{ + +#include +using namespace std; + +extern KateParser *parser; + +%} + +%locations + +%union { + int int_val; + double double_val; + bool bool_val; + char *string_val; + char *ident_val; + struct var *v; + void *ptr; +} + +%token TOK_NOT_EQUAL "!=" +%token TOK_LESSER_E "<=" +%token TOK_GREATER_E ">=" +%token TOK_EQUAL_2 "==" + +%type type type_proc + +%% + +prog: KW_PROGRAM ident { parser->start($2); } prog_beg_glob_decl instructions { parser->endproc(0); } dev_procedures KW_ENDP ; + +number: integer_number + | TOK_DOUBLE + { + $$ = new var; + $$->type = KW_REEL; + $$->cl = var::LITTERAL; + $$->real = $1; + }; + +%% + +#include + +int main(void) +{ + puts("Hello, World!"); + return 0; +} diff --git a/share/tests/hl/highlight1.spec b/share/tests/hl/highlight1.spec new file mode 100644 index 0000000..bc3b95b --- /dev/null +++ b/share/tests/hl/highlight1.spec @@ -0,0 +1,212 @@ +# Test file for rpmspec.xml + +# Comments start with a # in column="0": + +# Some comment + +# When they don't start in column="0", that they are recognized as comments, but with an alert: + # This is a bad comment. +# RPM spec says clear that comments must start at the begin of the line. However, in practice +# the RPM software is more permissive, depending on the context. But for our syntax highlighting, +# we give, while recognizing the as comment, at least a little alert. Comments should not contain +# the character % (which is marked as warning), but 2 of them are okay: %%. TODO is higlighted. + +# A spec file starts with "Normal" context. Here, you can specify values for some tags: +Name: kradioripper-unstable # Note that here in no comment possible! +Name: name only _one_ word allowed +Name: %macro no further syntax check after macro! +# Some tags support only _one_ word as value +Version: 0.4test5 up-from-the-space-this-is-an-error +# Some tag can have parameters: Any char in paranthesis: +Summary: Recorder for internet radios (based on Streamripper) +Summary(de.UTF-8): Aufnahmeprogramm für Internetradios (basiert auf Streamripper) +# requiere free text: +License: License 1 2 3 +# requiere a well defines value: +Requires( / ( = ): Some, value() +# new type "switch" accepts: yes, no, 0, 1 +AutoReq: yes +AutoReq: yes invalid +AutoReq: %macro no further syntax check after macro! +AutoReq: no +AutoReq: 0 +AutoReq: 1 +# requiere a number: +Epoch: 123123 +Epoch: 123123 invalid +Epoch: %macro no further syntax check afer macro! +# If tags are used that are not known, they are not highlighted: +Invalidtag: Some value +Invalid content in this section (only tags are allowed) + +# You can use conditions in specs (highlighted with region markers): +%if 0%{?mandriva_version} +# numbers and strings are distingished: string: +%if lsdksfj +# number: +%if 23472398 +# string: +%if lksdjfsl72939 +# invalid: +%if 92437lsdkfjdsl +# valid: +%if "lsdfj %ksdf(sdfs) 3489" +Release: %mkrel 1.2 +%else +Release: 0 +%endif +# requiere a well defined value: +%ifos fixed_value +# You must use these special macros (%%if etc.) always at the start of the line - if not, +# that's bad but not an arror. You must also always use the specified form. Everything else is an +# error: + %if +something %if +%{if} +%if(some options) +# However, this are different macros and therefore correct: +%ifx +%{ifx} +%ifx(some options) + +# the \ is escaped in the line. At the end of the line it escapes the line break: +echo This is \" a text \\ and here\ +it continues. + +%define name value +%define invalid_näme value +%define macroname multi\ +line content with references like %0 %* %# %{-f} %{-f*} %1 %2 and so on +%global name value +%global invalid_näme value +%undefine name +%undefine name too-many-parameters + +# This special comment is treated and highlighted like a tag: +# norootforbuild +# It can't have parameters, so every following non-whitespace character is not good: +# norootforbuild DONT WRITE ANYTHING HERE! +# wrong spacing is also recognized: +# norootforbuild +# and also an indeet is not fine for norootforbuild: + # norootforbuild + +# This following "Conflicts" tag will be removed by set-version.sh, +# if it is a "kradioripper" release (and not a "kradioripper-unstable" release)... +Conflicts: kradioripper + + +%description +# Here, a new section starts. It contains a value for the RPM field "description" and is therefor +# colored like values: +A KDE program for ripping internet radios. Based on StreamRipper. + + +# A section start can have parameters: +%description -l de.UTF-8 +Ein KDE-Aufnahmeprogramm für Internetradios. Basiert auf StreamRipper. + +# These sections starts are errors: + %description not at the first line +%{description} wrong form +%description(no options allowed, only parameters!) + + +%prep +# This starts a section that defines the commands to prepare the build. +# q means quit. n sets the directory: +%setup -q -n kradioripper +echo Test +# Macros can have different forms: Valid: +%abc +%abcÄndOfMacro +%abc(def)EndOfMacro +%{abc}EndOfMacro +%{something but no single %}EndOfMacro +%{abc:def}EndOfMacro +%(abc) +# Invalid: +%ÄInvalidChar +% +%) +%} +# You can use macros inside of macro calls: Fine: +%{something %but no %{sin%(fine)gle} }EndOfMacro +# Bad: +%{No closing paranthesis (No syntax highlightig for this error available) + + +%build +cmake ./ -DCMAKE_INSTALL_PREFIX=%{_prefix} +%__make %{?jobs:-j %jobs} + + +%install +%if 0%{?suse_version} +%makeinstall +%suse_update_desktop_file kradioripper +%endif +%if 0%{?fedora_version} || 0%{?rhel_version} || 0%{?centos_version} +make install DESTDIR=%{buildroot} +desktop-file-install --delete-original --vendor fedora --dir=%{buildroot}/%{_datadir}/applications/kde4 %{buildroot}/%{_datadir}/applications/kde4/kradioripper.desktop +%endif +%if 0%{?mandriva_version} +%makeinstall_std +%endif + + +%clean +rm -rf "%{buildroot}" + + +%files +%defattr(-,root,root) +%if 0%{?fedora_version} || 0%{?rhel_version} || 0%{?centos_version} +%{_datadir}/applications/kde4/fedora-kradioripper.desktop +%else +%{_datadir}/applications/kde4/kradioripper.desktop +%endif +%{_bindir}/kradioripper +%{_datadir}/locale/*/LC_MESSAGES/kradioripper.mo +%if 0%{?mandriva_version} +# TODO The %%doc macro is actually broken for mandriva 2009 in build service... +%dir %{_datadir}/apps/kradioripper +%{_datadir}/apps/kradioripper/* +%else +%doc COPYING LICENSE LICENSE.GPL2 LICENSE.GPL3 NEWS WARRANTY +%dir %{_datadir}/kde4/apps/kradioripper +%{_datadir}/kde4/apps/kradioripper/* +%endif + + +%changelog +* Sun May 04 2008 email@email.com +- some text +- some text + in two lines +- some text + in two lines + + with subtext + - and more subtext + in two lines +* Tue Apr 24 2007 Name +- text + * When the star isn't at column 0, than it doesn't indicate + a new date +* Wen Sep 08 2003 Wrong weekday +* Mon Mai 08 2003 Wrong month +* Mon Sep 0 2003 bad day +* Mon Sep 8 2003 good day +* Mon Sep 08 2003 good day +* Mon Sep 32 2003 bad day +* Mon Sep 08 03 bad year +* Mon Sep 08 2003 Name +# When using macros, the error check is disabled: +* %myDataMacro Title of the entry +- Text + - can + - be + - indeeded + - without + - problems + diff --git a/share/tests/hl/highlight_lpc.c b/share/tests/hl/highlight_lpc.c new file mode 100644 index 0000000..fe5c629 --- /dev/null +++ b/share/tests/hl/highlight_lpc.c @@ -0,0 +1,64 @@ +// NOTE: This is a test file for kate's LPC syntax highlighting. + +// This is a Single-Line Comment +/* This is a Multi- + Line Comment */ + +// This again is a Single-Line Comment which should end here /* + +// And this is an evil single line comment \ + which should include this and the next line because of the \ + Do not use this style at home, kids. +// BEGIN region marker + +// END of region marker + +private void create() +{ +// Some Preprocessor stuff: +#define SOME_STUFF if(foo("bar")) \ + { \ + bar("foo"); \ + } // Preprocessor, Keyword, Preprocessor-String, Multiline + + // Some closures: + #'create; + #'?!; + + + /* Some other Data Types: */ + + int i = 1; // Integer. + float b = 2.34; // Float. + int c = 0b001; // Binary + int e = 0x019Beef; // Hexadecimal + int f = 0o2345; // Octal + string a = "Wheee"; // String + string x = "Wheee\ + heee"; // Multi-Line String, again, don't use this. + + + + /* Some keywords: */ + if(1) + { + switch(2) + { + case 3: + 4; + break; + } + } + + else + { + return 0; + } +} + +/* +WARNING: If the above function is part of a multi-line comment, + it's buggy. The WARNING: itself should be a comment-keyword. + That's not actually part of the language, but simply used + to highlight important stuff inside comments like TODO: etc. +*/ diff --git a/share/tests/hl/highlight_ocaml.ml b/share/tests/hl/highlight_ocaml.ml new file mode 100644 index 0000000..dc1717a --- /dev/null +++ b/share/tests/hl/highlight_ocaml.ml @@ -0,0 +1,105 @@ +(* ocaml test file -- a big stew of Objective Caml syntax to use to + test Kate's syntax highlighting. This will not run! :-) *) + +(* First a little piece of real OCaml that should look right: *) + + #load "basic";; + (* Return a default value for a BASIC variable given its identifer. *) + let default_value (ident : string) : basic_value = + assert (String.length ident > 0); + match ident.[String.length ident - 1] with + | '$' -> Str "" + | '%' -> Int 0 + | '!' -> Flt 0.0 + | _ -> Flt 0.0 + ;; + +(* Directives: *) +#load "pa_o";; + #load "pa_o";; +object # meth ;; (* not a directive - a method call *) +object + # meth ;; (* not a directive - a method call *) + +(* OCaml keywords: *) +and as assert asr (* etc. there so many... *) + +(* Additional OCaml Revised Syntax keywords: *) +(* These are in a seperate category so they can be coloured to look + like identifiers when ordinary OCaml syntax is being used: *) +declare where value + +(* There's no way to reliably highlight all OCaml type expressions, + (they can be very complex) so just the built-in type names are highlighted.*) +exn lazy_t format unit int real char string ref array bool list option + + +let integers : int list = [ + 123456789; (* decimal *) + -0xabcedf0123456789; (* hexadecimal *) + 0xABCDEF0123456789; (* hexadecimal *) + -0o1234567; (* octal *) + 0b01001010101010; (* binary *) + -0Xabcedf0123456789; (* hexadecimal *) + 0XABCDEF0123456789; (* hexadecimal *) + -0O1234567; (* octal *) + 0B01001010101010; (* binary *) + -123_456_789; (* Underscores are allowed in numeric constants. *) + 0x_abce_df01_2345_6789; + -0o12_34_567; + 0b_0100_1010_1010_1101; +];; + +let floats : real list = [ + 12345.6789; + -1.23456789e4; (* All variations of the exponent form *) + 1.23456789e+4; + -1.23456789e-4; + 1.23456789E-4; + -1.23456789E+4; + 12_345.6789; (* Underscores are allowed in numeric constants. *) + -1.23_456_789e+4; + 12_345.6789; +];; + +let characters : char list = [ + 'a'; + ' '; + ''; + '\n'; '\r'; '\t'; '\b'; (* Control characters. Only these four: not the full C-language range. *) + '\000'; '\128'; (* Decimal character codes. These are always 3 digits. *) + '\x02'; '\xff'; '\xFF'; (* Hexadecimal character codes. These are always 3 digits. *) + '\\'; '\''; '\"'; '"' (* Quote character escapes. *) +];; + +(* Quotes used to mark constants in parsers should + not be confused with character constant quotes. + "Ticks" at the end of identifiers should + not be confused with character constant quotes. *) +let basic_identifier = + parser + [< ''F'; ''N'; name = s >] -> ID (s, 'f') + | [< name = s' >] -> ID (s','i') +;; + +let strings : string list = [ + ""; (* Empty string *) + "a"; " "; ""; "ab"; + "A\nB"; "A\rB"; "A\tB"; "A\bB"; (* Control characters. Only these four: not the full C-language range. *) + "A\000B"; "A\128B"; (* Decimal character codes. These are always 3 digits. *) + "A\x02B"; "A\xffB"; "A\xFFB"; (* Hexadecimal character codes. These are always 3 digits. *) + "A\\B"; "A\'B"; "A'B"; "A\"B"; (* Quote character escapes. *) + "A multiline\ + string"; +]; + +let camlp4_quotations = [ + <> ; + <:QUOTE> ; + <:QUT> ; + << A quote with an escape: \>> (end-quote symbol) >> ; + << A quote with an escape: \<< (plain start quote-symbol) >> ; + << A quote with an escape: \<:Trouv< (labelled start-quote symbol) >> ; +];; + +(* end *) diff --git a/share/tests/hl/highlight_octave.m b/share/tests/hl/highlight_octave.m new file mode 100644 index 0000000..1f96036 --- /dev/null +++ b/share/tests/hl/highlight_octave.m @@ -0,0 +1,74 @@ +##===================================================== +% Octave test code for Kate/Kwrite syntax highlighting +% (shamelessly copied from Matlab's, since the two +% are very similar) +% kate: hl Octave; +##===================================================== + +% Numbers _____________________________________________ +5, 5.5, .1, 0.1, 0.4e5, 1.2e-5, 5i, 5.3i, 6j, .345+3i +5', 5.5', .1', 0.1', 0.4e5', 1.2e-5', 5i', 5.3i', 6j', .345+3i' + +% Operators ___________________________________________ +% relational operators +'asdf'~=4, c<=4, d>=4, ab, a==b, b||c, b&&c +% elementwise arithmetic operators +a.^b, a.*b a./b, 1:4:5 +% single-character binary arithmetic +a+3, a-3, a*2, a^3, a/3, a\3, a|b, a&b +% unary operators +a = ~g; g = @sfdgdsf(sdfsd,345); g.' + 1i.' - ('asdf').' +% separators and delimiter +(asd),[sadf];{asdf},;;,;;;() +% continuation +a = 1+ ... + 2; + +% Strings and adjoint _________________________________ +% incomplete strings +'string +'str'' +'str''ing +'str''\' +% complete strings +'string' % simple string +'''' '\'' % strings containing ' +'str''ing' % one string containing ' +'string' 'string' % two strings +'asdf' "asdf""" variable % two strings and a variable +'asdf''asdf'' fsgdfg' + (asdf)' - 'asdf'.' + []''''.';'' +'sadf'.' % string transpose +% adjoint +{'asdf'}' + 1 +('asdf')' + 1 +['asdf']' + 1 +'' var''' % empty string, var with >1 adjoints +[5]'*{5}'*('asd')'.'+(5)'*6'*asdf'*asdf'.' % many adjoints +A'*B + 1 % adjoint +A.'*B + 1 % transpose +A.'.'*B + 1 % double transpose +A'.' + 1 % adjoint, then transpose +A.'' % transpose, then adjoint + +% System command ______________________________________ +!hostname +!cp * /tmp + +% Reserved keywords ___________________________________ +function, persistent, global +endfunction + +switch, case, otherwise +endswitch + +if, else, elseif +endif + +try, end_try_catch +for, while, break, continue +endfor + +endwhile +return +function, FUNCTION, Function % case sensitive! +endfunction \ No newline at end of file diff --git a/share/tests/hl/test.js b/share/tests/hl/test.js new file mode 100644 index 0000000..2dfe86c --- /dev/null +++ b/share/tests/hl/test.js @@ -0,0 +1,134 @@ +/* test.js - test for javascript.xml syntax file */ +// Note: this script will not, and is not supposed to, comile in any js engine. + +/* + NOTE: The words "todo", "fixme" and "note" should be rendered in a different style + within comments, match should be caseless (to test for regexp insensitive attribute). + The regex used for this rule is */ + String = /\b(?:fixme|todo|note)\b/ + /* Thus, for example "Notebook" is not caught by + this rule. (the "?:" in the subpattern is there to avoid the regex engine wasting time + saving a backref, which is not used for anything. I do not know if the overhead of parsing + that is greater than the time saved by not capturing the text...) + The rule for catching these words is placed in a context "Comment common", which is used + by both comment contexts (single line, multiline) using the new "IncludeRules" item. +*/ + +// test if regex support works - nice with new fallthrough prop in context:) +somestring.replace( /dooh/ , "bah!"); +re=/foo/ig; // hehe + +somestring.search( + /^foo\w+\s\d{0,15}$/ + ); + + re = + /dooh/; + +// This is supposedly legal: +re = somebool ? /foo/ : /bar/; + +// NOTE - Special case: an empty regex, not a comment. +// The rule uses a positive lookahead assertion to catch it: "//(?=;)". +re = //; +re = /a|b/; + +/* + Tests for the regex parser. + It will parse classes, quanitfiers, special characters and regex operaters, + as specified in the netscape documentation for javascript. + Regexps are only parsed in their clean form, as the RegExp(string) constructor + is using a quoted string. + TODO: Find out if more regex feats should be supported. + Consider using more itemDatas - assertion, quantifier are options. +*/ + +re = /^text\s+\d+\s*$/; +re = /a pattern with caret \(^\) in it/; +re = /(\d{0,4})\D/; +re = /[a-zA-Z_]+/; +re = /[^\d^]+/; +re = /\s+?\w+\.$/; +re = /\/\//; +re = /a|b/; + +// a test if #pop back from a comment will work +re = /*/foo/*/ /bar/; +// ^ POP +// ^ we got back after pop in comment, if there is regexp attribs here :-) + +/* + Some tests if the fallthrough works. + The fallthrough happens if a regexp is not found in a possible (!) position, + which is after "search(" or "replace(" or "=" or "?" or ":" in version 0.1 of the xml file +*/ + +var foo = 'bar'; +// ^ fallthrough! + + +somestring.replace( new RegExp("\\b\\w+\\b"), "word: $1"); +// ^ fallthrough expected. ("new" whould be bold) + + +something.method = + function ( a, b, c ) { /* ... */ } +// ^ fallthrough ?! + +something.other = +function ( d, e, f ) { /* ... */ } +// fallthrough expected at col 0 ("function" should be bold) + +var ary = new Array(5); +// ^ fallthrough ? (if keyword is correctly rendered) + +var b = a ? 1 : 0; +// ^ ^ fallthroughs. numbers must be rendered correctly. + +var c = d ? true : false; + +var conditinalstring = b ? + "something" : + "something else"; +// guess... + + +/* + Normal program flow... +*/ + +if (something) + dostuff(); +else + dont(); + + return; + +try { bla() } catch (e) { alert("ERROR! : " + e) } + +for (int i=0; i < j; i++) + document.write("i is" + i + "
"); + +while (something) +{ + block(); + picky: + if (!1) + break; + else + continue; +} + +with (a) { + do { + stuff( b ); // a.b if it exists + } while (itmakessense); +} + +switch (i) { + case 0: + f(); + break; + default: + break; +} diff --git a/share/tests/hl/verilog.v b/share/tests/hl/verilog.v new file mode 100644 index 0000000..00d18fb --- /dev/null +++ b/share/tests/hl/verilog.v @@ -0,0 +1,110 @@ +/* +// Verilog syntax highlighting test file. + * Ryan Dalzell, 19th October 2005 + * License: as-is + * NOTE This whole comment section should fold + * Testing the alerts: + * FIXME HACK NOTE NOTICE TASK TODO ### + */ + +`timescale 1ns/1ns // comment in a directive. +`define ns 1 + +// typical Verilog syntax. +module test (clock, reset, clear, enable, d, q); + + parameter param = 8; + parameter name = "test"; + localparam local = param*4; + + input clock; + input reset; + input clear; + input enable; + input [param-1:0] d; + output [param-1:0] q; + + wire [param-1:0] in; + wire [param-1:0] out; + + // a generate block, should also fold. + genvar i; + generate + for (i=0; i + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +//BEGIN Includes +#include "indenttest.h" + +#include "kateview.h" +#include "katedocument.h" +#include "katedocumenthelpers.h" +#include "kateconfig.h" +#include "katecmd.h" +#include "kateglobal.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "testutils.h" + +QTEST_KDEMAIN(IndentTest, GUI) + +/// somepath/kdelibs/part/tests/ +const QString srcPath(KDESRCDIR); +const QString testDataPath(KDESRCDIR "../../testdata/indent/"); + +#define FAILURE( test, comment ) qMakePair( (test), (comment) ) + +void IndentTest::initTestCase() +{ + KateGlobal::self()->incRef(); + m_toplevel = new KMainWindow(); + m_document = new KateDocument(true, false, false, m_toplevel); + m_view = static_cast(m_document->widget()); + m_env = new TestScriptEnv(m_document, m_outputWasCustomised); +} + +void IndentTest::cleanupTestCase() +{ + KateGlobal::self()->decRef(); +} + +void IndentTest::getTestData(const QString& indenter) +{ + QTest::addColumn("testcase"); + + // make sure the indenters are valid + QFile indenterFile(srcPath + "/../script/data/" + indenter + ".js"); + if (!indenterFile.exists()) { + QSKIP(qPrintable(QString(indenterFile.fileName() + " does not exist")), SkipAll); + } + QVERIFY(indenterFile.open(QFile::ReadOnly)); + QScriptValue result = m_env->engine()->evaluate(indenterFile.readAll(), indenterFile.fileName()); + QVERIFY2( !result.isError(), qPrintable(QString(result.toString() + "\nat " + + m_env->engine()->uncaughtExceptionBacktrace().join("\n"))) ); + + const QString testDir( testDataPath + indenter + '/' ); + if ( !QFile::exists(testDir) ) { + QSKIP(qPrintable(QString(testDir + " does not exist")), SkipAll); + } + QDirIterator contents( testDir ); + while ( contents.hasNext() ) { + QString entry = contents.next(); + if ( entry.endsWith('.') ) { + continue; + } + QFileInfo info(entry); + if ( !info.isDir() ) { + continue; + } + QTest::newRow( info.baseName().toLocal8Bit() ) << info.absoluteFilePath(); + } +} + +void IndentTest::runTest(const ExpectedFailures& failures) +{ + if ( !QFile::exists(testDataPath) ) + QSKIP(qPrintable(QString(testDataPath + " does not exist")), SkipAll); + + QFETCH(QString, testcase); + + m_toplevel->resize( 800, 600); // restore size + + // load page + KUrl url; + url.setProtocol("file"); + url.setPath(testcase + "/origin"); + m_document->openUrl(url); + + // evaluate test-script + QFile sourceFile(testcase + "/input.js"); + QVERIFY( sourceFile.open(QFile::ReadOnly) ); + + QTextStream stream(&sourceFile); + stream.setCodec("UTF8"); + QString code = stream.readAll(); + sourceFile.close(); + + // Execute script + QScriptValue result = m_env->engine()->evaluate(code, testcase + "/input.js", 1); + QVERIFY2( !result.isError(), result.toString().toUtf8().constData() ); + + url.setPath(testcase + "/actual"); + m_document->saveAs(url); + + // diff actual and expected + QProcess diff; + QStringList args; + args << "-u" << (testcase + "/expected") << (testcase + "/actual"); + diff.start("diff", args); + diff.waitForFinished(); + QByteArray out = diff.readAllStandardOutput(); + QByteArray err = diff.readAllStandardError(); + if ( !err.isEmpty() ) { + qWarning() << err; + } + foreach( const Failure& failure, failures ) { + QEXPECT_FAIL(failure.first, failure.second, Abort); + } + QCOMPARE(QString::fromLocal8Bit(out), QString()); + QCOMPARE(diff.exitCode(), EXIT_SUCCESS); + + m_document->closeUrl(); +} + +void IndentTest::cstyle_data() +{ + getTestData( "cstyle" ); +} + +void IndentTest::cstyle() +{ + runTest( ExpectedFailures() << FAILURE( "using1", "this is insane, those who write such code can cope with it :P" ) + << FAILURE( "using2", "this is insane, those who write such code can cope with it :P" ) + << FAILURE( "plist14", "in function signatures it might be wanted to use the indentation of the\n" + "opening paren instead of just increasing the indentation level like in function calls" ) + << FAILURE( "switch10", "test for case where cfgSwitchIndent = false; needs proper config-interface" ) + << FAILURE( "switch11", "test for case where cfgSwitchIndent = false; needs proper config-interface" ) + << FAILURE( "visib2", "test for access modifier where cfgAccessModifiers = 1;needs proper config interface" ) + << FAILURE( "visib3", "test for access modifier where cfgAccessModifiers = 1;needs proper config interface" ) + << FAILURE( "plist10", "low low prio, maybe wontfix: if the user wants to add a arg, he should do so and press enter afterwards" ) + << FAILURE( "switch13", "pure insanity, whoever wrote this test and expects that to be indented properly should stop writing code" ) + ); +} + + +void IndentTest::python_data() +{ + getTestData( "python" ); +} + +void IndentTest::python() +{ + m_document->config()->setIndentationMode("python"); + runTest( ExpectedFailures() ); +} + + +void IndentTest::haskell_data() +{ + getTestData( "haskell" ); +} + +void IndentTest::haskell() +{ + runTest( ExpectedFailures() ); +} + + +void IndentTest::ruby_data() +{ + getTestData( "ruby" ); +} + +void IndentTest::ruby() +{ + runTest( ExpectedFailures() << FAILURE( "block01", "Multiline blocks using {} is not supported" ) + << FAILURE( "block02", "Multiline blocks using {} is not supported" ) + << FAILURE( "singleline01", "Single line defs are not supported" ) + << FAILURE( "singleline02", "Single line defs are not supported" ) + << FAILURE( "wordlist01", "multiline word list is not supported" ) + << FAILURE( "wordlist02", "multiline word list is not supported" ) + << FAILURE( "wordlist11", "multiline word list is not supported" ) + << FAILURE( "wordlist12", "multiline word list is not supported" ) + << FAILURE( "wordlist21", "multiline word list is not supported" ) + << FAILURE( "wordlist22", "multiline word list is not supported" ) + << FAILURE( "if20", "multi line if assignment is not supported" ) + << FAILURE( "if21", "multi line if assignment is not supported" ) + << FAILURE( "if30", "single line if is not supported" ) + << FAILURE( "if31", "single line if is not supported" ) + ); +} + +void IndentTest::normal_data() +{ + getTestData( "normal" ); +} + +void IndentTest::normal() +{ + runTest( ExpectedFailures() << FAILURE( "emptyline1", "is that really what we expect?" ) + << FAILURE( "emptyline3", "is that really what we expext?" ) + ); +} diff --git a/share/tests/indenttest.h b/share/tests/indenttest.h new file mode 100644 index 0000000..db1465c --- /dev/null +++ b/share/tests/indenttest.h @@ -0,0 +1,66 @@ +/* + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License version 2 as published by the Free Software Foundation. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef INDENTTEST_H +#define INDENTTEST_H + +#include +#include +#include + +class TestScriptEnv; +class KateDocument; +class KateView; +class KMainWindow; + +class IndentTest : public QObject +{ + Q_OBJECT +private slots: + void initTestCase(); + void cleanupTestCase(); + + void python_data(); + void python(); + + void cstyle_data(); + void cstyle(); + + void ruby_data(); + void ruby(); + + void haskell_data(); + void haskell(); + + void normal_data(); + void normal(); + +private: + void getTestData(const QString& indenter); + + typedef QPair Failure; + typedef QList< Failure > ExpectedFailures; + void runTest(const ExpectedFailures& failures); + + TestScriptEnv* m_env; + KateDocument* m_document; + KMainWindow* m_toplevel; + bool m_outputWasCustomised; + QStringList m_commands; + KateView* m_view; +}; + +#endif // INDENTTEST_H diff --git a/share/tests/katedocument_test.cpp b/share/tests/katedocument_test.cpp new file mode 100644 index 0000000..3e676c5 --- /dev/null +++ b/share/tests/katedocument_test.cpp @@ -0,0 +1,331 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "katedocument_test.h" +#include "moc_katedocument_test.cpp" + +#include + +#include +#include +#include +#include + +///TODO: is there a FindValgrind cmake command we could use to +/// define this automatically? +// comment this out and run the test case with: +// valgrind --tool=callgrind --instr-atstart=no ./katedocument_test testSetTextPerformance +// or similar +// +// #define USE_VALGRIND + +#ifdef USE_VALGRIND + #include +#endif + +using namespace KTextEditor; + +QTEST_KDEMAIN(KateDocumentTest, GUI) + +namespace QTest { + template<> + char *toString(const KTextEditor::Cursor &cursor) + { + QByteArray ba = "Cursor[" + QByteArray::number(cursor.line()) + + ", " + QByteArray::number(cursor.column()) + "]"; + return qstrdup(ba.data()); + } +} + +class MovingRangeInvalidator : public QObject { + Q_OBJECT +public: + explicit MovingRangeInvalidator( QObject* parent = 0 ) + : QObject(parent) + { + } + + void addRange(MovingRange* range) + { + m_ranges << range; + } + QList ranges() const + { + return m_ranges; + } + +public slots: + void aboutToInvalidateMovingInterfaceContent() + { + qDeleteAll(m_ranges); + m_ranges.clear(); + } + +private: + QList m_ranges; +}; + + +KateDocumentTest::KateDocumentTest() + : QObject() +{ +} + +KateDocumentTest::~KateDocumentTest() +{ +} + +// tests: +// KateDocument::insertText with word wrap enabled. It is checked whether the +// text is correctly wrapped and whether the moving cursors maintain the correct +// position. +// see also: http://bugs.kde.org/show_bug.cgi?id=168534 +void KateDocumentTest::testWordWrap() +{ + KateDocument doc (false, false, false); + doc.setWordWrap(true); + doc.setWordWrapAt(80); + + const QString content = ".........1.........2.........3.........4.........5.........6 ........7 ........8"; + const QString firstWrap = ".........1.........2.........3.........4.........5.........6 ........7\n....x....8"; + const QString secondWrap = ".........1.........2.........3.........4.........5.........6\n....ooooooooooo....7 ....x....8"; + doc.setText(content); + MovingCursor* c = doc.newMovingCursor(Cursor(0, 75), MovingCursor::MoveOnInsert); + + QCOMPARE(doc.text(), content); + QCOMPARE(c->toCursor(), Cursor(0, 75)); + + // type a character at (0, 75) + doc.insertText (c->toCursor(), "x"); + QCOMPARE(doc.text(), firstWrap); + QCOMPARE(c->toCursor(), Cursor(1, 5)); + + // set cursor to (0, 65) and type "ooooooooooo" + c->setPosition(Cursor(0, 65)); + doc.insertText (c->toCursor(), "ooooooooooo"); + QCOMPARE(doc.text(), secondWrap); + QCOMPARE(c->toCursor(), Cursor(1, 15)); +} + +void KateDocumentTest::testReplaceQStringList() +{ + KateDocument doc(false, false, false); + doc.setWordWrap(false); + doc.setText("asdf\n" + "foo\n" + "foo\n" + "bar\n"); + doc.replaceText( Range(1, 0, 3, 0), QStringList() << "new" << "text" << "", false ); + QCOMPARE(doc.text(), QString("asdf\n" + "new\n" + "text\n" + "bar\n")); +} + +void KateDocumentTest::testRemoveTrailingSpace() +{ + // https://bugs.kde.org/show_bug.cgi?id=242611 + KateDocument doc(false, false, false); + doc.setText("asdf \t "); + doc.config()->setRemoveTrailingDyn(true); + doc.editRemoveText(0, 0, 1); + QCOMPARE(doc.text(), QString("sdf")); +} + +void KateDocumentTest::testMovingInterfaceSignals() +{ + KateDocument* doc = new KateDocument(false, false, false); + QSignalSpy aboutToDeleteSpy(doc, SIGNAL(aboutToDeleteMovingInterfaceContent(KTextEditor::Document*))); + QSignalSpy aboutToInvalidateSpy(doc, SIGNAL(aboutToInvalidateMovingInterfaceContent(KTextEditor::Document*))); + + QCOMPARE(doc->revision(), qint64(0)); + + QCOMPARE(aboutToInvalidateSpy.count(), 0); + QCOMPARE(aboutToDeleteSpy.count(), 0); + + KTemporaryFile f; + f.open(); + doc->openUrl(KUrl::fromLocalFile(f.fileName())); + QCOMPARE(doc->revision(), qint64(0)); + //TODO: gets emitted once in closeFile and once in openFile - is that OK? + QCOMPARE(aboutToInvalidateSpy.count(), 2); + QCOMPARE(aboutToDeleteSpy.count(), 0); + + doc->documentReload(); + QCOMPARE(doc->revision(), qint64(0)); + QCOMPARE(aboutToInvalidateSpy.count(), 4); + //TODO: gets emitted once in closeFile and once in openFile - is that OK? + QCOMPARE(aboutToDeleteSpy.count(), 0); + + delete doc; + QCOMPARE(aboutToInvalidateSpy.count(), 4); + QCOMPARE(aboutToDeleteSpy.count(), 1); +} + +void KateDocumentTest::testSetTextPerformance() +{ + const int lines = 150; + const int columns = 80; + const int rangeLength = 4; + const int rangeGap = 1; + + Q_ASSERT(columns % (rangeLength + rangeGap) == 0); + + KateDocument doc(false, false, false); + MovingRangeInvalidator invalidator; + connect(&doc, SIGNAL(aboutToInvalidateMovingInterfaceContent(KTextEditor::Document*)), + &invalidator, SLOT(aboutToInvalidateMovingInterfaceContent())); + + QString text; + QVector ranges; + ranges.reserve(lines * columns / (rangeLength + rangeGap)); + const QString line = QString().fill('a', columns); + for(int l = 0; l < lines; ++l) { + text.append(line); + text.append('\n'); + for(int c = 0; c < columns; c += rangeLength + rangeGap) { + ranges << Range(l, c, l, c + rangeLength); + } + } + + // replace + QBENCHMARK { + // init + doc.setText(text); + foreach(const Range& range, ranges) { + invalidator.addRange(doc.newMovingRange(range)); + } + QCOMPARE(invalidator.ranges().size(), ranges.size()); + + #ifdef USE_VALGRIND + CALLGRIND_START_INSTRUMENTATION + #endif + + doc.setText(text); + + #ifdef USE_VALGRIND + CALLGRIND_STOP_INSTRUMENTATION + #endif + + QCOMPARE(doc.text(), text); + QVERIFY(invalidator.ranges().isEmpty()); + } +} + +void KateDocumentTest::testRemoveTextPerformance() +{ + const int lines = 5000; + const int columns = 80; + + KateDocument doc(false, false, false); + + QString text; + const QString line = QString().fill('a', columns); + for(int l = 0; l < lines; ++l) { + text.append(line); + text.append('\n'); + } + + doc.setText(text); + + // replace + QBENCHMARK_ONCE { + #ifdef USE_VALGRIND + CALLGRIND_START_INSTRUMENTATION + #endif + + doc.editStart(); + + doc.removeText(doc.documentRange()); + + doc.editEnd(); + + #ifdef USE_VALGRIND + CALLGRIND_STOP_INSTRUMENTATION + #endif + } +} + +void KateDocumentTest::testForgivingApiUsage() +{ + KateDocument doc(false, false, false); + + QVERIFY(doc.isEmpty()); + QVERIFY(doc.replaceText(Range(0, 0, 100, 100), "asdf")); + QCOMPARE(doc.text(), QString("asdf")); + QCOMPARE(doc.lines(), 1); + QVERIFY(doc.replaceText(Range(2, 99, 2, 100), "asdf")); + QEXPECT_FAIL("", "replacing text behind the document end will add 5 lines out of nowhere", Continue); + QCOMPARE(doc.lines(), 3); + + QVERIFY(doc.removeText(Range(0, 0, 1000, 1000))); + QVERIFY(doc.removeText(Range(0, 0, 0, 100))); + QVERIFY(doc.isEmpty()); + doc.insertText(Cursor(100, 0), "foobar"); + QCOMPARE(doc.line(100), QString("foobar")); + + doc.setText("nY\nnYY\n"); + QVERIFY(doc.removeText(Range(0, 0, 0, 1000))); +} + +/** + * Provides slots to check data sent in specific signals. Slot names are derived from corresponding test names. + */ +class SignalHandler : public QObject +{ + Q_OBJECT +public slots: + void slotMultipleLinesRemoved(KTextEditor::Document*, const KTextEditor::Range&, const QString& oldText) + { + QCOMPARE(oldText, QString("line2\nline3\n")); + } + + void slotNewlineInserted(KTextEditor::Document*, const KTextEditor::Range& range) + { + QCOMPARE(range, Range(Cursor(1, 4), Cursor(2, 0))); + } +}; + +void KateDocumentTest::testRemoveMultipleLines() +{ + KateDocument doc(false, false, false); + + doc.setText("line1\n" + "line2\n" + "line3\n" + "line4\n"); + + SignalHandler handler; + connect(&doc, SIGNAL(textRemoved(KTextEditor::Document*,KTextEditor::Range,QString)), &handler, SLOT(slotMultipleLinesRemoved(KTextEditor::Document*,KTextEditor::Range,QString))); + doc.removeText(Range(1, 0, 3, 0)); +} + +void KateDocumentTest::testInsertNewline() +{ + KateDocument doc(false, false, false); + + doc.setText("this is line\n" + "this is line2\n"); + + SignalHandler handler; + connect(&doc, SIGNAL(textInserted(KTextEditor::Document*,KTextEditor::Range)), &handler, SLOT(slotNewlineInserted(KTextEditor::Document*,KTextEditor::Range))); + doc.editWrapLine(1, 4); +} + +#include "katedocument_test.moc" diff --git a/share/tests/katedocument_test.h b/share/tests/katedocument_test.h new file mode 100644 index 0000000..30c6753 --- /dev/null +++ b/share/tests/katedocument_test.h @@ -0,0 +1,48 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_DOCUMENT_TEST_H +#define KATE_DOCUMENT_TEST_H + +#include + +class KateDocumentTest : public QObject +{ + Q_OBJECT + +public: + KateDocumentTest(); + ~KateDocumentTest(); + +private Q_SLOTS: + void testWordWrap(); + void testReplaceQStringList(); + void testRemoveTrailingSpace(); + void testMovingInterfaceSignals(); + + void testSetTextPerformance(); + void testRemoveTextPerformance(); + + void testForgivingApiUsage(); + + void testRemoveMultipleLines(); + void testInsertNewline(); +}; + +#endif // KATE_DOCUMENT_TEST_H diff --git a/share/tests/katefolding_test.cpp b/share/tests/katefolding_test.cpp new file mode 100644 index 0000000..689dcdd --- /dev/null +++ b/share/tests/katefolding_test.cpp @@ -0,0 +1,419 @@ +/* This file is part of the Kate project. + * + * Copyright (C) 2011 Adrian Lungu + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "katefolding_test.h" + +#include + +#include +#include +#include +#include +#include + +using namespace KTextEditor; + +QTEST_KDEMAIN(KateFoldingTest, GUI) + + namespace QTest { + template<> + char *toString(const KTextEditor::Cursor &cursor) + { + QByteArray ba = "Cursor[" + QByteArray::number(cursor.line()) + + ", " + QByteArray::number(cursor.column()) + "]"; + return qstrdup(ba.data()); + } +} + +void KateFoldingTest::testFolding_data() +{ + QTest::addColumn("text"); + QTest::addColumn("fileExt"); + QTest::addColumn("firstActionName"); + QTest::addColumn("secondActionName"); + QTest::addColumn("initValue"); + QTest::addColumn("firstResult"); + QTest::addColumn("secondResult"); + + QString text; + text += "int main() {\n" ; + text += " asdf;\n"; + text += "}\n"; + + QTest::newRow("simple cpp folding test") << text << "cpp" << "folding_toplevel" << "folding_expandtoplevel" << 4u << 2u << 4u; + QTest::newRow("reload test") << text << "cpp" << "folding_toplevel" << "file_reload" << 4u << 2u << 2u; + + text = ""; + text += "int main() {\n" ; + text += " asdf;\n"; + text += " {;\n"; + text += " }\n"; + + QTest::newRow("fold unmatched '{' - test 1") << text << "cpp" << "collapse_level_2" << "folding_toplevel" << 5u << 4u << 1u; + QTest::newRow("fold unmatched '{' - test 2") << text << "cpp" << "folding_toplevel" << "collapse_level_2" << 5u << 1u << 1u; +} + +void KateFoldingTest::testFolding() +{ + QFETCH(QString, text); + QFETCH(QString, fileExt); + QFETCH(QString, firstActionName); + QFETCH(QString, secondActionName); + + QFETCH(unsigned int, initValue); + QFETCH(unsigned int, firstResult); + QFETCH(unsigned int, secondResult); + + KTemporaryFile file; + file.setSuffix("." + fileExt); + file.open(); + QTextStream stream(&file); + + stream << text; + stream << flush; + file.close(); + + KateDocument doc(false, false, false); + QVERIFY(doc.openUrl(KUrl(file.fileName()))); + + KateView* view = new KateView(&doc, 0); + + QAction* firstAction = view->action(qPrintable(firstActionName)); + QVERIFY(firstAction); + + QAction* secondAction = view->action(qPrintable(secondActionName)); + QVERIFY(secondAction); + + // is set to allow kate's hl to be called + view->config()->setDynWordWrap(true); + + QCOMPARE(doc.visibleLines(), initValue); + + firstAction->trigger(); + QCOMPARE(doc.visibleLines(), firstResult); + + secondAction->trigger(); + QCOMPARE(doc.visibleLines(), secondResult); +} + +void KateFoldingTest::testFoldingReload() +{ + KTemporaryFile file; + file.setSuffix(".cpp"); + file.open(); + QTextStream stream(&file); + stream << "int main() {\n" + << " asdf;\n" + << "}\n"; + stream << flush; + file.close(); + + KateDocument doc(false, false, false); + QVERIFY(doc.openUrl(KUrl(file.fileName()))); + + KateView* view = new KateView(&doc, 0); + + // is set to allow kate's hl to be called + view->config()->setDynWordWrap(true); + + QCOMPARE(doc.visibleLines(), 4u); + + QAction* action = view->action("folding_toplevel"); + QVERIFY(action); + action->trigger(); + + doc.foldingTree()->saveFoldingState(); + + QList hiddenLines(doc.foldingTree()->m_hiddenLines); + QList hiddenColumns(doc.foldingTree()->m_hiddenColumns); + + QCOMPARE(doc.visibleLines(), 2u); + + action = view->action("file_reload"); + QVERIFY(action); + action->trigger(); + + QCOMPARE(doc.visibleLines(), 2u); + + QCOMPARE(hiddenLines,doc.foldingTree()->m_hiddenLines); + QCOMPARE(hiddenColumns,doc.foldingTree()->m_hiddenColumns); +} + +void KateFoldingTest::testFolding_rb_lang() +{ + KTemporaryFile file; + file.setSuffix(".rb"); + file.open(); + QTextStream stream(&file); + stream << "if customerName == x\n" + << " print x\n" + << "elsif customerName == y\n" + << " print y\n" + << "else print z\n"; + stream << flush; + file.close(); + + KateDocument doc(false, false, false); + QVERIFY(doc.openUrl(KUrl(file.fileName()))); + + KateView* view = new KateView(&doc, 0); + + // is set to allow kate's hl to be called + view->config()->setDynWordWrap(true); + + QCOMPARE(doc.visibleLines(), 6u); + + QAction* action = view->action("folding_toplevel"); + QVERIFY(action); + action->trigger(); + QCOMPARE(doc.visibleLines(), 1u); + + action = view->action("folding_expandtoplevel"); + QVERIFY(action); + action->trigger(); + QCOMPARE(doc.visibleLines(), 6u); +} + +void KateFoldingTest::testFolding_py_lang() +{ + KTemporaryFile file; + file.setSuffix(".py"); + file.open(); + QTextStream stream(&file); + stream << "if customerName == x\n" + << " print x\n" + << "elif customerName == y\n" + << " print y\n" + << "else print z\n"; + stream << flush; + file.close(); + + KateDocument doc(false, false, false); + QVERIFY(doc.openUrl(KUrl(file.fileName()))); + + KateView* view = new KateView(&doc, 0); + + // is set to allow kate's hl to be called + view->config()->setDynWordWrap(true); + + QCOMPARE(doc.visibleLines(), 6u); + + QAction* action = view->action("folding_toplevel"); + QVERIFY(action); + action->trigger(); + QCOMPARE(doc.visibleLines(), 4u); + + action = view->action("folding_expandtoplevel"); + QVERIFY(action); + action->trigger(); + QCOMPARE(doc.visibleLines(), 6u); +} + +void KateFoldingTest::testFolding_expand_collapse_level234() +{ + KTemporaryFile file; + file.setSuffix(".c"); + file.open(); + QTextStream stream(&file); + stream << "if () {\n" + << " if () {\n" + << " if () {\n" + << " if () {\n" + << " }\n" + << " }\n" + << " }\n" + << " if () {\n" + << " foo()\n" + << " }\n" + << " }\n"; + stream << flush; + file.close(); + + KateDocument doc(false, false, false); + QVERIFY(doc.openUrl(KUrl(file.fileName()))); + + KateView* view = new KateView(&doc, 0); + + // is set to allow kate's hl to be called + view->config()->setDynWordWrap(true); + + QCOMPARE(doc.visibleLines(), 12u); + + QAction* action = view->action("collapse_level_4"); + QVERIFY(action); + action->trigger(); + QCOMPARE(doc.visibleLines(), 11u); + + action = view->action("collapse_level_3"); + QVERIFY(action); + action->trigger(); + QCOMPARE(doc.visibleLines(), 9u); + + action = view->action("collapse_level_2"); + QVERIFY(action); + action->trigger(); + QCOMPARE(doc.visibleLines(), 5u); + + action = view->action("folding_expandall"); + QVERIFY(action); + action->trigger(); + QCOMPARE(doc.visibleLines(), 12u); +} + +void KateFoldingTest::testFolding_collapse_expand_local() +{ + KTemporaryFile file; + file.setSuffix(".c"); + file.open(); + QTextStream stream(&file); + stream << "if () {\n" + << " if () {\n" + << " if () {\n" + << " if () {\n" + << " }\n" + << " }\n" + << " }\n" + << " if () {\n" + << " foo()\n" + << " }\n" + << " }\n"; + stream << flush; + file.close(); + + KateDocument doc(false, false, false); + QVERIFY(doc.openUrl(KUrl(file.fileName()))); + + KateView* view = new KateView(&doc, 0); + + // is set to allow kate's hl to be called + view->config()->setDynWordWrap(true); + + QCOMPARE(doc.visibleLines(), 12u); + + view->setCursorPosition(KTextEditor::Cursor(2,12)); + + QAction* action = view->action("folding_collapselocal"); + QVERIFY(action); + action->trigger(); + QCOMPARE(doc.visibleLines(), 9u); + + view->setCursorPosition(KTextEditor::Cursor(2,11)); + + action = view->action("folding_collapselocal"); + QVERIFY(action); + action->trigger(); + QCOMPARE(doc.visibleLines(), 7u); + + view->setCursorPosition(KTextEditor::Cursor(1,9)); + + action = view->action("folding_expandlocal"); + QVERIFY(action); + action->trigger(); + QCOMPARE(doc.visibleLines(), 9u); + +} + +void KateFoldingTest::testFolding_collapse_dsComments_C() +{ + KTemporaryFile file; + file.setSuffix(".c"); + file.open(); + QTextStream stream(&file); + stream << "{\n" + << "}\n" + << "/*\n" + << "{\n" + << "}\n" + << "*/\n" + << "/*\n" + << "*/\n"; + stream << flush; + file.close(); + + KateDocument doc(false, false, false); + QVERIFY(doc.openUrl(KUrl(file.fileName()))); + + KateView* view = new KateView(&doc, 0); + + // is set to allow kate's hl to be called + view->config()->setDynWordWrap(true); + + QCOMPARE(doc.visibleLines(), 9u); + + QAction* action = view->action("folding_collapse_dsComment"); + QVERIFY(action); + action->trigger(); + QCOMPARE(doc.visibleLines(), 5u); +} + +void KateFoldingTest::testFolding_collapse_dsComments_XML() +{ + KTemporaryFile file; + file.setSuffix(".xml"); + file.open(); + QTextStream stream(&file); + stream << "\n" + << "\n" + << "\n" + << "\n"; + stream << flush; + file.close(); + + KateDocument doc(false, false, false); + QVERIFY(doc.openUrl(KUrl(file.fileName()))); + + KateView* view = new KateView(&doc, 0); + + // is set to allow kate's hl to be called + view->config()->setDynWordWrap(true); + + QCOMPARE(doc.visibleLines(), 9u); + + QAction* action = view->action("folding_collapse_dsComment"); + QVERIFY(action); + action->trigger(); + QCOMPARE(doc.visibleLines(), 5u); +} + +void KateFoldingTest::testFindNodeForPosition() +{ + // see also: https://bugs.kde.org/show_bug.cgi?id=289469 + + KTemporaryFile file; + file.setSuffix(".cpp"); + file.open(); + QTextStream stream(&file); + stream << "int f() {\n" + << " int i;\n" + << "}\n"; + stream << flush; + file.close(); + + KateDocument doc(false, false, false); + QVERIFY(doc.openUrl(KUrl(file.fileName()))); + + QVERIFY(!doc.foldingTree()->findNodeForPosition(1, 0)); + QVERIFY(doc.foldingTree()->findNodeForLine(1)); + QVERIFY(doc.foldingTree()->findNodeForLine(0)); +} diff --git a/share/tests/katefolding_test.h b/share/tests/katefolding_test.h new file mode 100644 index 0000000..a3b0fa8 --- /dev/null +++ b/share/tests/katefolding_test.h @@ -0,0 +1,48 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Milian Wolff + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_FOLDING_TEST_H +#define KATE_FOLDING_TEST_H + +#include +#include "katecodefolding.h" + +class KateFoldingTest : public QObject +{ + //friend class KateCodeFoldingTree; + + Q_OBJECT + +//public: + +private Q_SLOTS: + + void testFolding_data(); + void testFolding(); + void testFoldingReload(); + void testFolding_py_lang(); + void testFolding_rb_lang(); + void testFolding_expand_collapse_level234(); + void testFolding_collapse_expand_local(); + void testFolding_collapse_dsComments_C(); + void testFolding_collapse_dsComments_XML(); + void testFindNodeForPosition(); +}; + +#endif // KATE_FOLDING_TEST_H diff --git a/share/tests/katetextbuffertest.cpp b/share/tests/katetextbuffertest.cpp new file mode 100644 index 0000000..5548145 --- /dev/null +++ b/share/tests/katetextbuffertest.cpp @@ -0,0 +1,207 @@ +/* This file is part of the Kate project. + * + * Copyright (C) 2010 Christoph Cullmann + * Copyright (C) 2010 Dominik Haumann + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "katetextbuffertest.h" +#include "katetextbuffer.h" +#include "katetextcursor.h" + +QTEST_MAIN(KateTextBufferTest) + +KateTextBufferTest::KateTextBufferTest() + : QObject() +{ +} + +KateTextBufferTest::~KateTextBufferTest() +{ +} + +void KateTextBufferTest::basicBufferTest() +{ + // construct an empty text buffer + Kate::TextBuffer buffer (0, 1); + + // one line per default + QVERIFY (buffer.lines() == 1); + QVERIFY (buffer.text () == ""); + + //FIXME: use QTestLib macros for checking the correct state + // start editing + buffer.startEditing (); + + // end editing + buffer.finishEditing (); +} + +void KateTextBufferTest::wrapLineTest() +{ + // construct an empty text buffer + Kate::TextBuffer buffer (0, 1); + + // wrap first empty line -> we should have two empty lines + buffer.startEditing (); + buffer.wrapLine(KTextEditor::Cursor(0, 0)); + buffer.finishEditing (); + buffer.debugPrint ("Two empty lines"); + QVERIFY (buffer.text () == "\n"); + + // unwrap again -> only one empty line + buffer.startEditing (); + buffer.unwrapLine(1); + buffer.finishEditing (); + + // print debug + buffer.debugPrint ("Empty Buffer"); + QVERIFY (buffer.text () == ""); +} + +void KateTextBufferTest::insertRemoveTextTest() +{ + // construct an empty text buffer + Kate::TextBuffer buffer (0, 1); + + // wrap first line + buffer.startEditing (); + buffer.wrapLine (KTextEditor::Cursor (0, 0)); + buffer.finishEditing (); + buffer.debugPrint ("Two empty lines"); + QVERIFY (buffer.text () == "\n"); + + // remember second line + Kate::TextLine second = buffer.line (1); + + // unwrap second line + buffer.startEditing (); + buffer.unwrapLine (1); + buffer.finishEditing (); + buffer.debugPrint ("One empty line"); + QVERIFY (buffer.text () == ""); + + // second text line should be still there + //const QString &secondText = second->text (); + //QVERIFY (secondText == "") + + // insert text + buffer.startEditing (); + buffer.insertText (KTextEditor::Cursor (0, 0), "testremovetext"); + buffer.finishEditing (); + buffer.debugPrint ("One line"); + QVERIFY (buffer.text () == "testremovetext"); + + // remove text + buffer.startEditing (); + buffer.removeText (KTextEditor::Range (KTextEditor::Cursor (0, 4), KTextEditor::Cursor (0, 10))); + buffer.finishEditing (); + buffer.debugPrint ("One line"); + QVERIFY (buffer.text () == "testtext"); + + // wrap text + buffer.startEditing (); + buffer.wrapLine (KTextEditor::Cursor (0, 2)); + buffer.finishEditing (); + buffer.debugPrint ("Two line"); + QVERIFY (buffer.text () == "te\nsttext"); + + // unwrap text + buffer.startEditing (); + buffer.unwrapLine (1); + buffer.finishEditing (); + buffer.debugPrint ("One line"); + QVERIFY (buffer.text () == "testtext"); +} + +void KateTextBufferTest::cursorTest() +{ + // last buffer content, for consistence checks + QString lastBufferContent; + + // test with different block sizes + for (int i = 1; i <= 4; ++i) { + // construct an empty text buffer + Kate::TextBuffer buffer (0, i); + + // wrap first line + buffer.startEditing (); + buffer.insertText (KTextEditor::Cursor (0, 0), "sfdfjdsklfjlsdfjlsdkfjskldfjklsdfjklsdjkfl"); + buffer.wrapLine (KTextEditor::Cursor (0, 8)); + buffer.wrapLine (KTextEditor::Cursor (1, 8)); + buffer.wrapLine (KTextEditor::Cursor (2, 8)); + buffer.finishEditing (); + buffer.debugPrint ("Cursor buffer"); + + // construct cursor + Kate::TextCursor *cursor1 = new Kate::TextCursor (buffer, KTextEditor::Cursor (0, 0), Kate::TextCursor::MoveOnInsert); + QVERIFY (cursor1->toCursor () == KTextEditor::Cursor (0, 0)); + printf ("cursor %d, %d\n", cursor1->line(), cursor1->column()); + + Kate::TextCursor *cursor2 = new Kate::TextCursor (buffer, KTextEditor::Cursor (1, 8), Kate::TextCursor::MoveOnInsert); + printf ("cursor %d, %d\n", cursor2->line(), cursor2->column()); + + Kate::TextCursor *cursor3 = new Kate::TextCursor (buffer, KTextEditor::Cursor (0, 123), Kate::TextCursor::MoveOnInsert); + printf ("cursor %d, %d\n", cursor3->line(), cursor3->column()); + + Kate::TextCursor *cursor4 = new Kate::TextCursor (buffer, KTextEditor::Cursor (1323, 1), Kate::TextCursor::MoveOnInsert); + printf ("cursor %d, %d\n", cursor4->line(), cursor4->column()); + + // insert text + buffer.startEditing (); + buffer.insertText (KTextEditor::Cursor (0, 0), "hallo"); + buffer.finishEditing (); + buffer.debugPrint ("Cursor buffer"); + + printf ("cursor %d, %d\n", cursor1->line(), cursor1->column()); + QVERIFY (cursor1->toCursor () == KTextEditor::Cursor (0, 5)); + + // remove text + buffer.startEditing (); + buffer.removeText (KTextEditor::Range (KTextEditor::Cursor (0, 4), KTextEditor::Cursor (0, 10))); + buffer.finishEditing (); + buffer.debugPrint ("Cursor buffer"); + + printf ("cursor %d, %d\n", cursor1->line(), cursor1->column()); + QVERIFY (cursor1->toCursor () == KTextEditor::Cursor (0, 4)); + + // wrap line + buffer.startEditing (); + buffer.wrapLine (KTextEditor::Cursor (0, 3)); + buffer.finishEditing (); + buffer.debugPrint ("Cursor buffer"); + + printf ("cursor %d, %d\n", cursor1->line(), cursor1->column()); + QVERIFY (cursor1->toCursor () == KTextEditor::Cursor (1, 1)); + + // unwrap line + buffer.startEditing (); + buffer.unwrapLine (1); + buffer.finishEditing (); + buffer.debugPrint ("Cursor buffer"); + + printf ("cursor %d, %d\n", cursor1->line(), cursor1->column()); + QVERIFY (cursor1->toCursor () == KTextEditor::Cursor (0, 4)); + + // verify content + if (i > 1) + QVERIFY (lastBufferContent == buffer.text ()); + + // remember content + lastBufferContent = buffer.text (); + } +} diff --git a/share/tests/katetextbuffertest.h b/share/tests/katetextbuffertest.h new file mode 100644 index 0000000..3eb08ba --- /dev/null +++ b/share/tests/katetextbuffertest.h @@ -0,0 +1,42 @@ +/* This file is part of the Kate project. + * + * Copyright (C) 2010 Christoph Cullmann + * Copyright (C) 2010 Dominik Haumann + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef KATEBUFFERTEST_H +#define KATEBUFFERTEST_H + +#include +#include + +class KateTextBufferTest : public QObject +{ + Q_OBJECT + + public: + KateTextBufferTest(); + virtual ~KateTextBufferTest(); + + private Q_SLOTS: + void basicBufferTest(); + void wrapLineTest(); + void insertRemoveTextTest(); + void cursorTest(); +}; + +#endif // KATEBUFFERTEST_H diff --git a/share/tests/kateview_test.cpp b/share/tests/kateview_test.cpp new file mode 100644 index 0000000..ae4b206 --- /dev/null +++ b/share/tests/kateview_test.cpp @@ -0,0 +1,294 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Milian Wolff + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kateview_test.h" +#include "moc_kateview_test.cpp" + +#include + +#include +#include +#include +#include +#include +#include + +using namespace KTextEditor; + +QTEST_KDEMAIN(KateViewTest, GUI) + +namespace QTest { + template<> + char *toString(const KTextEditor::Cursor &cursor) + { + QByteArray ba = "Cursor[" + QByteArray::number(cursor.line()) + + ", " + QByteArray::number(cursor.column()) + "]"; + return qstrdup(ba.data()); + } +} + + +KateViewTest::KateViewTest() + : QObject() +{ +} + +KateViewTest::~KateViewTest() +{ +} + +void KateViewTest::testReloadMultipleViews() +{ + KTemporaryFile file; + file.setSuffix(".cpp"); + file.open(); + QTextStream stream(&file); + const QString line = "const char* foo = \"asdf\"\n"; + for ( int i = 0; i < 200; ++i ) { + stream << line; + } + stream << flush; + file.close(); + + KateDocument doc(false, false, false); + QVERIFY(doc.openUrl(KUrl(file.fileName()))); + QCOMPARE(doc.highlightingMode(), QString("C++")); + + KateView* view1 = new KateView(&doc, 0); + KateView* view2 = new KateView(&doc, 0); + view1->show(); + view2->show(); + QCOMPARE(doc.views().count(), 2); + + QVERIFY(doc.documentReload()); +} + +void KateViewTest::testLowerCaseBlockSelection() +{ + // testcase for https://bugs.kde.org/show_bug.cgi?id=258480 + KateDocument doc(false, false, false); + doc.setText("nY\nnYY\n"); + + KateView* view1 = new KateView(&doc, 0); + view1->setBlockSelectionMode(true); + view1->setSelection(Range(0, 1, 1, 3)); + view1->lowercase(); + + QCOMPARE(doc.text(), QString("ny\nnyy\n")); +} + +void KateViewTest::testFolding_data() +{ + QTest::addColumn("dynWordWrap"); + QTest::addColumn("scrollPastEnd"); + QTest::addColumn("autoCenterLines"); + + QTest::newRow("dynWordWrap") << true << false << 0; + QTest::newRow("dynWordWrap+scrollPastEnd") << true << true << 0; + QTest::newRow("dynWordWrap+autoCenterLines") << true << false << 10; + QTest::newRow("dynWordWrap+scrollPastEnd+autoCenterLines") << true << true << 10; + QTest::newRow("scrollPastEnd") << false << true << 0; + QTest::newRow("scrollPastEnd+autoCenterLines") << false << true << 10; +} + +void KateViewTest::testFolding() +{ + KTemporaryFile file; + file.setSuffix(".cpp"); + file.open(); + QTextStream stream(&file); + stream << "int main() {\n" + << " asdf;\n" + << "}\n"; + stream << flush; + file.close(); + + KateDocument doc(false, false, false); + QVERIFY(doc.openUrl(KUrl(file.fileName()))); + QCOMPARE(doc.highlightingMode(), QString("C++")); + + KateView* view = new KateView(&doc, 0); + QAction* collapseAction = view->action("folding_toplevel"); + QVERIFY(collapseAction); + QAction* expandAction = view->action("folding_expandtoplevel"); + QVERIFY(expandAction); + + QFETCH(bool, dynWordWrap); + QFETCH(bool, scrollPastEnd); + QFETCH(int, autoCenterLines); + + view->config()->setDynWordWrap(dynWordWrap); + view->config()->setScrollPastEnd(scrollPastEnd); + view->config()->setAutoCenterLines(autoCenterLines); + + for(int i = 0; i < doc.lines(); ++i) { + doc.buffer().ensureHighlighted(i); + } + QCOMPARE(doc.visibleLines(), 4u); + + collapseAction->trigger(); + QCOMPARE(doc.visibleLines(), 2u); + + expandAction->trigger(); + QCOMPARE(doc.visibleLines(), 4u); +} + +void KateViewTest::testBug287291() +{ + // see also: https://bugs.kde.org/show_bug.cgi?id=287291 + KTemporaryFile file; + file.setSuffix(".cpp"); + file.open(); + QTextStream stream(&file); + stream << "int main() {\n" + << " asdf;\n" + << "}\n"; + stream << flush; + file.close(); + + KateDocument doc(false, false, false); + QVERIFY(doc.openUrl(KUrl(file.fileName()))); + QCOMPARE(doc.highlightingMode(), QString("C++")); + + KateView* view = new KateView(&doc, 0); + QAction* collapseAction = view->action("folding_toplevel"); + QVERIFY(collapseAction); + QAction* expandAction = view->action("folding_expandtoplevel"); + QVERIFY(expandAction); + + for(int i = 0; i < doc.lines(); ++i) { + doc.buffer().ensureHighlighted(i); + // make sure this works without crash + KateLineInfo info; + doc.lineInfo(&info, i); + } + + QCOMPARE(doc.visibleLines(), 4u); + collapseAction->trigger(); + QCOMPARE(doc.visibleLines(), 2u); + for(int i = 0; i < doc.lines(); ++i) { + // make sure this works without crash + KateLineInfo info; + doc.lineInfo(&info, i); + } + doc.clear(); + QCOMPARE(doc.visibleLines(), 1u); + doc.undo(); + QCOMPARE(doc.visibleLines(), 5u); + for(int i = 0; i < doc.lines(); ++i) { + // make sure this works without crash + KateLineInfo info; + doc.lineInfo(&info, i); + } + + // now add a newline after the last } + QCOMPARE(doc.text(Range(2, 0, 2, 1)), QLatin1String("}")); + view->setCursorPosition(Cursor(2, 1)); + doc.newLine(view); + for(int i = 0; i < doc.lines(); ++i) { + // make sure this works without crash + KateLineInfo info; + doc.lineInfo(&info, i); + } +} + + +void KateViewTest::testSelection() +{ + // see also: https://bugs.kde.org/show_bug.cgi?id=277422 + // wrong behavior before: + // Open file with text + // click at end of some line (A) and drag to right, i.e. without selecting anything + // click somewhere else (B) + // shift click to another place (C) + // => expected: selection from B to C + // => actual: selection from A to C + + KTemporaryFile file; + file.setSuffix(".txt"); + file.open(); + QTextStream stream(&file); + stream << "A\n" + << "B\n" + << "C"; + stream << flush; + file.close(); + + KateDocument doc(false, false, false); + QVERIFY(doc.openUrl(KUrl(file.fileName()))); + + KateView* view = new KateView(&doc, 0); + view->resize(100, 100); + view->show(); + + // hackish but works: access to KateViewInternal + QObject* internalView = view->childAt(50, 50); + QCOMPARE(internalView->metaObject()->className(), "KateViewInternal"); + + const QPoint afterA = view->cursorToCoordinate(Cursor(0, 1)); + const QPoint afterB = view->cursorToCoordinate(Cursor(1, 1)); + const QPoint afterC = view->cursorToCoordinate(Cursor(2, 1)); + + // click after A + QCoreApplication::sendEvent(internalView, new QMouseEvent(QEvent::MouseButtonPress, afterA, + Qt::LeftButton, Qt::LeftButton, + Qt::NoModifier)); + + QCoreApplication::sendEvent(internalView, new QMouseEvent(QEvent::MouseButtonRelease, afterA, + Qt::LeftButton, Qt::LeftButton, + Qt::NoModifier)); + QCOMPARE(view->cursorPosition(), Cursor(0, 1)); + // drag to right + QCoreApplication::sendEvent(internalView, new QMouseEvent(QEvent::MouseButtonPress, afterA, + Qt::LeftButton, Qt::LeftButton, + Qt::NoModifier)); + + QCoreApplication::sendEvent(internalView, new QMouseEvent(QEvent::MouseMove, afterA + QPoint(50, 0), + Qt::LeftButton, Qt::LeftButton, + Qt::NoModifier)); + + QCoreApplication::sendEvent(internalView, new QMouseEvent(QEvent::MouseButtonRelease, afterA + QPoint(50, 0), + Qt::LeftButton, Qt::LeftButton, + Qt::NoModifier)); + + QCOMPARE(view->cursorPosition(), Cursor(0, 1)); + QVERIFY(!view->selection()); + + // click after C + QCoreApplication::sendEvent(internalView, new QMouseEvent(QEvent::MouseButtonPress, afterC, + Qt::LeftButton, Qt::LeftButton, + Qt::NoModifier)); + + QCoreApplication::sendEvent(internalView, new QMouseEvent(QEvent::MouseButtonRelease, afterC, + Qt::LeftButton, Qt::LeftButton, + Qt::NoModifier)); + + QCOMPARE(view->cursorPosition(), Cursor(2, 1)); + // shift+click after B + QCoreApplication::sendEvent(internalView, new QMouseEvent(QEvent::MouseButtonPress, afterB, + Qt::LeftButton, Qt::LeftButton, + Qt::ShiftModifier)); + + QCoreApplication::sendEvent(internalView, new QMouseEvent(QEvent::MouseButtonRelease, afterB, + Qt::LeftButton, Qt::LeftButton, + Qt::ShiftModifier)); + + QCOMPARE(view->cursorPosition(), Cursor(1, 1)); + QCOMPARE(view->selectionRange(), Range(1, 1, 2, 1)); +} diff --git a/share/tests/kateview_test.h b/share/tests/kateview_test.h new file mode 100644 index 0000000..09f4780 --- /dev/null +++ b/share/tests/kateview_test.h @@ -0,0 +1,46 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Milian Wolff + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_VIEW_TEST_H +#define KATE_VIEW_TEST_H + +#include + +class KateViewTest : public QObject +{ + Q_OBJECT + +public: + KateViewTest(); + ~KateViewTest(); + +private Q_SLOTS: + void testReloadMultipleViews(); + + void testLowerCaseBlockSelection(); + + void testFolding_data(); + void testFolding(); + + void testBug287291(); + + void testSelection(); +}; + +#endif // KATE_VIEW_TEST_H diff --git a/share/tests/kte_documentcursor.cpp b/share/tests/kte_documentcursor.cpp new file mode 100644 index 0000000..f3361fe --- /dev/null +++ b/share/tests/kte_documentcursor.cpp @@ -0,0 +1,280 @@ +/* This file is part of the KDE libraries + Copyright (C) 2012 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "kte_documentcursor.h" +#include "moc_kte_documentcursor.cpp" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +QTEST_KDEMAIN(DocumentCursorTest, GUI) + +using namespace KTextEditor; + +DocumentCursorTest::DocumentCursorTest() + : QObject() +{ +} + +DocumentCursorTest::~DocumentCursorTest() +{ +} + +void DocumentCursorTest::initTestCase() +{ + KateGlobal::self()->incRef(); +} + +void DocumentCursorTest::cleanupTestCase() +{ + KateGlobal::self()->decRef(); +} + +// tests: +// - atStartOfDocument +// - atStartOfLine +// - atEndOfDocument +// - atEndOfLine +// - move forward with Wrap +// - move forward with NoWrap +// - move backward +// - gotoNextLine +// - gotoPreviousLine +void DocumentCursorTest::testConvenienceApi() +{ + KateDocument doc (false, false, false); + doc.setText("\n" + "1\n" + "22\n" + "333\n" + "4444\n" + "55555"); + + // check start and end of document + DocumentCursor startOfDoc(&doc); startOfDoc.setPosition(Cursor(0, 0)); + DocumentCursor endOfDoc(&doc); endOfDoc.setPosition(Cursor(5, 5)); + QVERIFY(startOfDoc.atStartOfDocument()); + QVERIFY(startOfDoc.atStartOfLine()); + QVERIFY(endOfDoc.atEndOfDocument()); + QVERIFY(endOfDoc.atEndOfLine()); + + // set cursor to (2, 2) and then move to the left two times + DocumentCursor moving(&doc); moving.setPosition(Cursor(2, 2)); + QVERIFY(moving.atEndOfLine()); // at 2, 2 + QVERIFY(moving.move(-1)); // at 2, 1 + QCOMPARE(moving.toCursor(), Cursor(2, 1)); + QVERIFY(!moving.atEndOfLine()); + QVERIFY(moving.move(-1)); // at 2, 0 + QCOMPARE(moving.toCursor(), Cursor(2, 0)); + QVERIFY(moving.atStartOfLine()); + + // now move again to the left, should wrap to (1, 1) + QVERIFY(moving.move(-1)); // at 1, 1 + QCOMPARE(moving.toCursor(), Cursor(1, 1)); + QVERIFY(moving.atEndOfLine()); + + // advance 7 characters to position (3, 3) + QVERIFY(moving.move(7)); // at 3, 3 + QCOMPARE(moving.toCursor(), Cursor(3, 3)); + + // advance 20 characters in NoWrap mode, then go back 10 characters + QVERIFY(moving.move(20, DocumentCursor::NoWrap)); // at 3, 23 + QCOMPARE(moving.toCursor(), Cursor(3, 23)); + QVERIFY(moving.move(-10)); // at 3, 13 + QCOMPARE(moving.toCursor(), Cursor(3, 13)); + + // still at invalid text position. move one char to wrap around + QVERIFY(!moving.isValidTextPosition()); // at 3, 13 + QVERIFY(moving.move(1)); // at 4, 0 + QCOMPARE(moving.toCursor(), Cursor(4, 0)); + + // moving 11 characters in wrap mode moves to (5, 6), which is not a valid + // text position anymore. Hence, moving should be rejected. + QVERIFY(!moving.move(11)); + QVERIFY(moving.move(10)); + QVERIFY(moving.atEndOfDocument()); + + // try to move to next line, which fails. then go to previous line + QVERIFY(!moving.gotoNextLine()); + QVERIFY(moving.gotoPreviousLine()); + QCOMPARE(moving.toCursor(), Cursor(4, 0)); +} + +void DocumentCursorTest::testOperators() +{ + KateDocument doc (false, false, false); + doc.setText("--oo--\n" + "--oo--\n" + "--oo--"); + + // create lots of cursors for comparison + Cursor invalid = Cursor::invalid(); + Cursor c02(0, 2); + Cursor c04(0, 4); + Cursor c14(1, 4); + + DocumentCursor m02(&doc); + DocumentCursor m04(&doc); + DocumentCursor m14(&doc); + + QVERIFY(m02 == invalid); + QVERIFY(m04 == invalid); + QVERIFY(m14 == invalid); + + m02.setPosition(Cursor(0, 2)); + m04.setPosition(Cursor(0, 4)); + m14.setPosition(Cursor(1, 4)); + + // invalid comparison + QVERIFY(invalid == invalid); + QVERIFY(invalid <= c02); + QVERIFY(invalid < c02); + QVERIFY(!(invalid > c02)); + QVERIFY(!(invalid >= c02)); + + QVERIFY(!(invalid == m02)); + QVERIFY(invalid <= m02); + QVERIFY(invalid < m02); + QVERIFY(!(invalid > m02)); + QVERIFY(!(invalid >= m02)); + + QVERIFY(!(m02 == invalid)); + QVERIFY(!(m02 <= invalid)); + QVERIFY(!(m02 < invalid)); + QVERIFY(m02 > invalid); + QVERIFY(m02 >= invalid); + + // DocumentCursor <-> DocumentCursor + QVERIFY(m02 == m02); + QVERIFY(m02 <= m02); + QVERIFY(m02 >= m02); + QVERIFY(!(m02 < m02)); + QVERIFY(!(m02 > m02)); + QVERIFY(!(m02 != m02)); + + QVERIFY(!(m02 == m04)); + QVERIFY(m02 <= m04); + QVERIFY(!(m02 >= m04)); + QVERIFY(m02 < m04); + QVERIFY(!(m02 > m04)); + QVERIFY(m02 != m04); + + QVERIFY(!(m04 == m02)); + QVERIFY(!(m04 <= m02)); + QVERIFY(m04 >= m02); + QVERIFY(!(m04 < m02)); + QVERIFY(m04 > m02); + QVERIFY(m04 != m02); + + QVERIFY(!(m02 == m14)); + QVERIFY(m02 <= m14); + QVERIFY(!(m02 >= m14)); + QVERIFY(m02 < m14); + QVERIFY(!(m02 > m14)); + QVERIFY(m02 != m14); + + QVERIFY(!(m14 == m02)); + QVERIFY(!(m14 <= m02)); + QVERIFY(m14 >= m02); + QVERIFY(!(m14 < m02)); + QVERIFY(m14 > m02); + QVERIFY(m14 != m02); + + // DocumentCursor <-> Cursor + QVERIFY(m02 == c02); + QVERIFY(m02 <= c02); + QVERIFY(m02 >= c02); + QVERIFY(!(m02 < c02)); + QVERIFY(!(m02 > c02)); + QVERIFY(!(m02 != c02)); + + QVERIFY(!(m02 == c04)); + QVERIFY(m02 <= c04); + QVERIFY(!(m02 >= c04)); + QVERIFY(m02 < c04); + QVERIFY(!(m02 > c04)); + QVERIFY(m02 != c04); + + QVERIFY(!(m04 == c02)); + QVERIFY(!(m04 <= c02)); + QVERIFY(m04 >= c02); + QVERIFY(!(m04 < c02)); + QVERIFY(m04 > c02); + QVERIFY(m04 != c02); + + QVERIFY(!(m02 == c14)); + QVERIFY(m02 <= c14); + QVERIFY(!(m02 >= c14)); + QVERIFY(m02 < c14); + QVERIFY(!(m02 > c14)); + QVERIFY(m02 != c14); + + QVERIFY(!(m14 == c02)); + QVERIFY(!(m14 <= c02)); + QVERIFY(m14 >= c02); + QVERIFY(!(m14 < c02)); + QVERIFY(m14 > c02); + QVERIFY(m14 != c02); + + // Cursor <-> DocumentCursor + QVERIFY(c02 == m02); + QVERIFY(c02 <= m02); + QVERIFY(c02 >= m02); + QVERIFY(!(c02 < m02)); + QVERIFY(!(c02 > m02)); + QVERIFY(!(c02 != m02)); + + QVERIFY(!(c02 == m04)); + QVERIFY(c02 <= m04); + QVERIFY(!(c02 >= m04)); + QVERIFY(c02 < m04); + QVERIFY(!(c02 > m04)); + QVERIFY(c02 != m04); + + QVERIFY(!(c04 == m02)); + QVERIFY(!(c04 <= m02)); + QVERIFY(c04 >= m02); + QVERIFY(!(c04 < m02)); + QVERIFY(c04 > m02); + QVERIFY(c04 != m02); + + QVERIFY(!(c02 == m14)); + QVERIFY(c02 <= m14); + QVERIFY(!(c02 >= m14)); + QVERIFY(c02 < m14); + QVERIFY(!(c02 > m14)); + QVERIFY(c02 != m14); + + QVERIFY(!(c14 == m02)); + QVERIFY(!(c14 <= m02)); + QVERIFY(c14 >= m02); + QVERIFY(!(c14 < m02)); + QVERIFY(c14 > m02); + QVERIFY(c14 != m02); +} diff --git a/share/tests/kte_documentcursor.h b/share/tests/kte_documentcursor.h new file mode 100644 index 0000000..ccb2283 --- /dev/null +++ b/share/tests/kte_documentcursor.h @@ -0,0 +1,41 @@ +/* This file is part of the KDE libraries + Copyright (C) 2012 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KTE_DOCUMENTCURSOR_TEST_H +#define KTE_DOCUMENTCURSOR_TEST_H + +#include + +class DocumentCursorTest : public QObject +{ + Q_OBJECT + +public: + DocumentCursorTest(); + ~DocumentCursorTest(); + +private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + void testConvenienceApi(); + void testOperators(); +}; + +#endif diff --git a/share/tests/modificationsystem_test.cpp b/share/tests/modificationsystem_test.cpp new file mode 100644 index 0000000..65ba6f1 --- /dev/null +++ b/share/tests/modificationsystem_test.cpp @@ -0,0 +1,742 @@ +/* This file is part of the KDE libraries + Copyright (C) 2011 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "modificationsystem_test.h" +#include "moc_modificationsystem_test.cpp" + +#include + +#include +#include +#include +#include + +QTEST_KDEMAIN(ModificationSystemTest, GUI) + +using namespace KTextEditor; + +void ModificationSystemTest::initTestCase() +{ + KateGlobal::self()->incRef(); +} + +void ModificationSystemTest::cleanupTestCase() +{ + KateGlobal::self()->decRef(); +} + +static void clearModificationFlags(KateDocument* doc) +{ + for (int i = 0; i < doc->lines(); ++i) { + Kate::TextLine line = doc->plainKateTextLine(i); + line->markAsModified(false); + line->markAsSavedOnDisk(false); + } +} + +static void markModifiedLinesAsSaved(KateDocument* doc) +{ + for (int i = 0; i < doc->lines(); ++i) { + Kate::TextLine textLine = doc->plainKateTextLine(i); + if (textLine->markedAsModified()) + textLine->markAsSavedOnDisk(true); + } +} + +void ModificationSystemTest::testInsertText() +{ + KateDocument* doc = qobject_cast(KateGlobal::self()->createDocument(0)); + + const QString content("first line\n"); + doc->setText(content); + + Kate::TextLine line0 = doc->plainKateTextLine(0); + + // now all lines should have state "Modified" + QVERIFY(line0->markedAsModified()); + QVERIFY(!line0->markedAsSavedOnDisk()); + + + // clear all modification flags, forces no flags + doc->setModified(false); + doc->undoManager()->updateLineModifications(); + clearModificationFlags(doc); + + QVERIFY(!line0->markedAsModified()); + QVERIFY(!line0->markedAsSavedOnDisk()); + + // now we have an a unmodified file, start real tests + // insert text in line 0, then undo and redo + doc->insertText(Cursor(0, 2), "_"); + QVERIFY(line0->markedAsModified()); + QVERIFY(!line0->markedAsSavedOnDisk()); + + doc->undo(); + QVERIFY(!line0->markedAsModified()); + QVERIFY(line0->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(line0->markedAsModified()); + QVERIFY(!line0->markedAsSavedOnDisk()); + + + // + // now simulate "save", then do the undo/redo tests again + // + doc->setModified(false); + markModifiedLinesAsSaved(doc); + doc->undoManager()->updateLineModifications(); + + // now no line should have state "Modified" + QVERIFY(!line0->markedAsModified()); + QVERIFY(line0->markedAsSavedOnDisk()); + + // undo the text insertion + doc->undo(); + QVERIFY(line0->markedAsModified()); + QVERIFY(!line0->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(!line0->markedAsModified()); + QVERIFY(line0->markedAsSavedOnDisk()); + + delete doc; +} + +void ModificationSystemTest::testRemoveText() +{ + KateDocument* doc = qobject_cast(KateGlobal::self()->createDocument(0)); + + const QString content("first line\n"); + doc->setText(content); + + Kate::TextLine line0 = doc->plainKateTextLine(0); + + // now all lines should have state "Modified" + QVERIFY(line0->markedAsModified()); + QVERIFY(!line0->markedAsSavedOnDisk()); + + + // clear all modification flags, forces no flags + doc->setModified(false); + doc->undoManager()->updateLineModifications(); + clearModificationFlags(doc); + + QVERIFY(!line0->markedAsModified()); + QVERIFY(!line0->markedAsSavedOnDisk()); + + // now we have an a unmodified file, start real tests + // remove text in line 0, then undo and redo + doc->removeText(Range(Cursor(0, 1), Cursor(0, 2))); + QVERIFY(line0->markedAsModified()); + QVERIFY(!line0->markedAsSavedOnDisk()); + + doc->undo(); + QVERIFY(!line0->markedAsModified()); + QVERIFY(line0->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(line0->markedAsModified()); + QVERIFY(!line0->markedAsSavedOnDisk()); + + + // + // now simulate "save", then do the undo/redo tests again + // + doc->setModified(false); + markModifiedLinesAsSaved(doc); + doc->undoManager()->updateLineModifications(); + + // now no line should have state "Modified" + QVERIFY(!line0->markedAsModified()); + QVERIFY(line0->markedAsSavedOnDisk()); + + // undo the text insertion + doc->undo(); + QVERIFY(line0->markedAsModified()); + QVERIFY(!line0->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(!line0->markedAsModified()); + QVERIFY(line0->markedAsSavedOnDisk()); + + delete doc; +} + +void ModificationSystemTest::testInsertLine() +{ + KateDocument* doc = qobject_cast(KateGlobal::self()->createDocument(0)); + + const QString content("0\n" + "2"); + doc->setText(content); + + // clear all modification flags, forces no flags + doc->setModified(false); + doc->undoManager()->updateLineModifications(); + clearModificationFlags(doc); + + // insert at line 1 + doc->insertLine(1, "1"); + + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + doc->undo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + + // + // now simulate "save", then do the undo/redo tests again + // + doc->setModified(false); + markModifiedLinesAsSaved(doc); + doc->undoManager()->updateLineModifications(); + + // now no line should have state "Modified" + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + // undo the text insertion + doc->undo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + delete doc; +} + +void ModificationSystemTest::testRemoveLine() +{ + KateDocument* doc = qobject_cast(KateGlobal::self()->createDocument(0)); + + const QString content("0\n" + "1\n" + "2"); + doc->setText(content); + + // clear all modification flags, forces no flags + doc->setModified(false); + doc->undoManager()->updateLineModifications(); + clearModificationFlags(doc); + + // remove at line 1 + doc->removeLine(1); + + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + doc->undo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + + // + // now simulate "save", then do the undo/redo tests again + // + doc->setModified(false); + markModifiedLinesAsSaved(doc); + doc->undoManager()->updateLineModifications(); + + // now no line should have state "Modified" + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + // undo the text insertion + doc->undo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + delete doc; +} + +void ModificationSystemTest::testWrapLineMid() +{ + for (int i = 0; i < 2; ++i) { + bool insertNewLine = (i == 1); + KateDocument* doc = qobject_cast(KateGlobal::self()->createDocument(0)); + + const QString content("aaaa\n" + "bbbb\n" + "cccc"); + doc->setText(content); + + // clear all modification flags, forces no flags + doc->setModified(false); + doc->undoManager()->updateLineModifications(); + clearModificationFlags(doc); + + // wrap line 1 at |: bb|bb + doc->editWrapLine(1, 2, insertNewLine); + + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + doc->undo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + + // + // now simulate "save", then do the undo/redo tests again + // + doc->setModified(false); + markModifiedLinesAsSaved(doc); + doc->undoManager()->updateLineModifications(); + + // now no line should have state "Modified" + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + // undo the text insertion + doc->undo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + delete doc; + } +} + +void ModificationSystemTest::testWrapLineAtEnd() +{ + KateDocument* doc = qobject_cast(KateGlobal::self()->createDocument(0)); + + const QString content("aaaa\n" + "bbbb"); + doc->setText(content); + + // clear all modification flags, forces no flags + doc->setModified(false); + doc->undoManager()->updateLineModifications(); + clearModificationFlags(doc); + + // wrap line 0 at end + doc->editWrapLine(0, 4); + + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + doc->undo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + + // + // now simulate "save", then do the undo/redo tests again + // + doc->setModified(false); + markModifiedLinesAsSaved(doc); + doc->undoManager()->updateLineModifications(); + + // now no line should have state "Modified" + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + // undo the text insertion + doc->undo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + delete doc; +} + +void ModificationSystemTest::testWrapLineAtStart() +{ + KateDocument* doc = qobject_cast(KateGlobal::self()->createDocument(0)); + + const QString content("aaaa\n" + "bbbb"); + doc->setText(content); + + // clear all modification flags, forces no flags + doc->setModified(false); + doc->undoManager()->updateLineModifications(); + clearModificationFlags(doc); + + // wrap line 0 at end + doc->editWrapLine(0, 0); + + QVERIFY(doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + doc->undo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + + // + // now simulate "save", then do the undo/redo tests again + // + doc->setModified(false); + markModifiedLinesAsSaved(doc); + doc->undoManager()->updateLineModifications(); + + // now no line should have state "Modified" + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + // undo the text insertion + doc->undo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + delete doc; +} + +void ModificationSystemTest::testUnWrapLine() +{ + KateDocument* doc = qobject_cast(KateGlobal::self()->createDocument(0)); + + const QString content("aaaa\n" + "bbbb\n" + "cccc"); + doc->setText(content); + + // clear all modification flags, forces no flags + doc->setModified(false); + doc->undoManager()->updateLineModifications(); + clearModificationFlags(doc); + + // join line 0 and 1 + doc->editUnWrapLine(0); + + QVERIFY(doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + doc->undo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + + // + // now simulate "save", then do the undo/redo tests again + // + doc->setModified(false); + markModifiedLinesAsSaved(doc); + doc->undoManager()->updateLineModifications(); + + // now no line should have state "Modified" + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + // undo the text insertion + doc->undo(); + QVERIFY(doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + delete doc; +} + +void ModificationSystemTest::testUnWrapLine1Empty() +{ + KateDocument* doc = qobject_cast(KateGlobal::self()->createDocument(0)); + + const QString content("aaaa\n" + "\n" + "bbbb"); + doc->setText(content); + + // clear all modification flags, forces no flags + doc->setModified(false); + doc->undoManager()->updateLineModifications(); + clearModificationFlags(doc); + + // join line 1 and 2 + doc->editUnWrapLine(1); + + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + doc->undo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + + // + // now simulate "save", then do the undo/redo tests again + // + doc->setModified(false); + markModifiedLinesAsSaved(doc); + doc->undoManager()->updateLineModifications(); + + // now no line should have state "Modified" + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + // undo the text insertion + doc->undo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + delete doc; +} + +void ModificationSystemTest::testUnWrapLine2Empty() +{ + KateDocument* doc = qobject_cast(KateGlobal::self()->createDocument(0)); + + const QString content("aaaa\n" + "\n" + "bbbb"); + doc->setText(content); + + // clear all modification flags, forces no flags + doc->setModified(false); + doc->undoManager()->updateLineModifications(); + clearModificationFlags(doc); + + // join line 0 and 1 + doc->editUnWrapLine(0); + + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + doc->undo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + + // + // now simulate "save", then do the undo/redo tests again + // + doc->setModified(false); + markModifiedLinesAsSaved(doc); + doc->undoManager()->updateLineModifications(); + + // now no line should have state "Modified" + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + // undo the text insertion + doc->undo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(2)->markedAsSavedOnDisk()); + + doc->redo(); + QVERIFY(!doc->plainKateTextLine(0)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsModified()); + QVERIFY(!doc->plainKateTextLine(0)->markedAsSavedOnDisk()); + QVERIFY(!doc->plainKateTextLine(1)->markedAsSavedOnDisk()); + + delete doc; +} + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/share/tests/modificationsystem_test.h b/share/tests/modificationsystem_test.h new file mode 100644 index 0000000..d1f1d39 --- /dev/null +++ b/share/tests/modificationsystem_test.h @@ -0,0 +1,56 @@ +/* This file is part of the KDE libraries + Copyright (C) 2011 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_MODIFICATION_SYSTEM_TEST_H +#define KATE_MODIFICATION_SYSTEM_TEST_H + +#include + +/** + * Test the complete Line Modification System. + * Covered classes: + * - KateModification* in part/undo/ + * - modification flags in Kate::TextLine in part/buffer/ + */ +class ModificationSystemTest : public QObject +{ + Q_OBJECT + + private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + void testInsertText(); + void testRemoveText(); + + void testInsertLine(); + void testRemoveLine(); + + void testWrapLineMid(); + void testWrapLineAtEnd(); + void testWrapLineAtStart(); + + void testUnWrapLine(); + void testUnWrapLine1Empty(); + void testUnWrapLine2Empty(); +}; + +#endif + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/share/tests/movingcursor_test.cpp b/share/tests/movingcursor_test.cpp new file mode 100644 index 0000000..a279b81 --- /dev/null +++ b/share/tests/movingcursor_test.cpp @@ -0,0 +1,327 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "movingcursor_test.h" +#include "moc_movingcursor_test.cpp" + +#include + +#include +#include + +using namespace KTextEditor; + +QTEST_KDEMAIN(MovingCursorTest, GUI) + +namespace QTest { + template<> + char *toString(const KTextEditor::Cursor &cursor) + { + QByteArray ba = "Cursor[" + QByteArray::number(cursor.line()) + + ", " + QByteArray::number(cursor.column()) + "]"; + return qstrdup(ba.data()); + } +} + +MovingCursorTest::MovingCursorTest() + : QObject() +{ +} + +MovingCursorTest::~MovingCursorTest() +{ +} + +// tests: +// - MovingCursor with StayOnInsert +// - MovingCursor with MoveOnInsert +void MovingCursorTest::testMovingCursor() +{ + KateDocument doc (false, false, false); + MovingCursor* invalid = doc.newMovingCursor(Cursor::invalid()); + MovingCursor* moveOnInsert = doc.newMovingCursor(Cursor(0, 0), MovingCursor::MoveOnInsert); + MovingCursor* stayOnInsert = doc.newMovingCursor(Cursor(0, 0), MovingCursor::StayOnInsert); + + // verify initial conditions + QVERIFY(!invalid->isValid()); + QCOMPARE(moveOnInsert->toCursor(), Cursor(0, 0)); + QCOMPARE(stayOnInsert->toCursor(), Cursor(0, 0)); + + // insert some text + doc.insertText(Cursor(0, 0), "\n" + "1\n" + "22"); + + // check new cursor positions + QCOMPARE(moveOnInsert->toCursor(), Cursor(2, 2)); + QCOMPARE(stayOnInsert->toCursor(), Cursor(0, 0)); + + // set position to (1, 1) and insert text before cursor + stayOnInsert->setPosition(Cursor(1, 1)); + QCOMPARE(stayOnInsert->toCursor(), Cursor(1, 1)); + doc.insertText(Cursor(1, 0), "test"); + QCOMPARE(stayOnInsert->toCursor(), Cursor(1, 5)); + doc.undo(); + QCOMPARE(stayOnInsert->toCursor(), Cursor(1, 1)); + + // position still at (1, 1). insert text at cursor + doc.insertText(Cursor(1, 1), "test"); + QCOMPARE(stayOnInsert->toCursor(), Cursor(1, 1)); + doc.undo(); + QCOMPARE(stayOnInsert->toCursor(), Cursor(1, 1)); + + // + // same tests with the moveOnInsert cursor + // + // set position to (1, 1) and insert text before cursor + moveOnInsert->setPosition(Cursor(1, 1)); + QCOMPARE(moveOnInsert->toCursor(), Cursor(1, 1)); + doc.insertText(Cursor(1, 0), "test"); + QCOMPARE(moveOnInsert->toCursor(), Cursor(1, 5)); + doc.undo(); + QCOMPARE(moveOnInsert->toCursor(), Cursor(1, 1)); + + // position still at (1, 1). insert text at cursor + doc.insertText(Cursor(1, 1), "test"); + QCOMPARE(moveOnInsert->toCursor(), Cursor(1, 5)); + doc.undo(); + QCOMPARE(moveOnInsert->toCursor(), Cursor(1, 1)); + + // set both cursors to (2, 1) then delete text range that contains cursors + moveOnInsert->setPosition(Cursor(2, 1)); + stayOnInsert->setPosition(Cursor(2, 1)); + doc.removeText(Range(Cursor(2, 0), Cursor(2, 2))); + QCOMPARE(moveOnInsert->toCursor(), Cursor(2, 0)); + QCOMPARE(moveOnInsert->toCursor(), Cursor(2, 0)); +} + +// tests: +// - atStartOfDocument +// - atStartOfLine +// - atEndOfDocument +// - atEndOfLine +// - move forward with Wrap +// - move forward with NoWrap +// - move backward +// - gotoNextLine +// - gotoPreviousLine +void MovingCursorTest::testConvenienceApi() +{ + KateDocument doc (false, false, false); + doc.setText("\n" + "1\n" + "22\n" + "333\n" + "4444\n" + "55555"); + + // check start and end of document + MovingCursor *startOfDoc = doc.newMovingCursor(Cursor(0, 0)); + MovingCursor *endOfDoc = doc.newMovingCursor(Cursor(5, 5)); + QVERIFY(startOfDoc->atStartOfDocument()); + QVERIFY(startOfDoc->atStartOfLine()); + QVERIFY(endOfDoc->atEndOfDocument()); + QVERIFY(endOfDoc->atEndOfLine()); + + // set cursor to (2, 2) and then move to the left two times + MovingCursor *moving = doc.newMovingCursor(Cursor(2, 2)); + QVERIFY(moving->atEndOfLine()); // at 2, 2 + QVERIFY(moving->move(-1)); // at 2, 1 + QCOMPARE(moving->toCursor(), Cursor(2, 1)); + QVERIFY(!moving->atEndOfLine()); + QVERIFY(moving->move(-1)); // at 2, 0 + QCOMPARE(moving->toCursor(), Cursor(2, 0)); + QVERIFY(moving->atStartOfLine()); + + // now move again to the left, should wrap to (1, 1) + QVERIFY(moving->move(-1)); // at 1, 1 + QCOMPARE(moving->toCursor(), Cursor(1, 1)); + QVERIFY(moving->atEndOfLine()); + + // advance 7 characters to position (3, 3) + QVERIFY(moving->move(7)); // at 3, 3 + QCOMPARE(moving->toCursor(), Cursor(3, 3)); + + // advance 20 characters in NoWrap mode, then go back 10 characters + QVERIFY(moving->move(20, MovingCursor::NoWrap)); // at 3, 23 + QCOMPARE(moving->toCursor(), Cursor(3, 23)); + QVERIFY(moving->move(-10)); // at 3, 13 + QCOMPARE(moving->toCursor(), Cursor(3, 13)); + + // still at invalid text position. move one char to wrap around + QVERIFY(!moving->isValidTextPosition()); // at 3, 13 + QVERIFY(moving->move(1)); // at 4, 0 + QCOMPARE(moving->toCursor(), Cursor(4, 0)); + + // moving 11 characters in wrap mode moves to (5, 6), which is not a valid + // text position anymore. Hence, moving should be rejected. + QVERIFY(!moving->move(11)); + QVERIFY(moving->move(10)); + QVERIFY(moving->atEndOfDocument()); + + // try to move to next line, which fails. then go to previous line + QVERIFY(!moving->gotoNextLine()); + QVERIFY(moving->gotoPreviousLine()); + QCOMPARE(moving->toCursor(), Cursor(4, 0)); +} + +void MovingCursorTest::testOperators() +{ + KateDocument doc (false, false, false); + doc.setText("--oo--\n" + "--oo--\n" + "--oo--"); + + // create lots of cursors for comparison + Cursor invalid = Cursor::invalid(); + Cursor c02(0, 2); + Cursor c04(0, 4); + Cursor c14(1, 4); + + MovingCursor* m02 = doc.newMovingCursor(Cursor(0, 2)); + MovingCursor* m04 = doc.newMovingCursor(Cursor(0, 4)); + MovingCursor* m14 = doc.newMovingCursor(Cursor(1, 4)); + + // invalid comparison + QVERIFY(invalid == invalid); + QVERIFY(invalid <= c02); + QVERIFY(invalid < c02); + QVERIFY(!(invalid > c02)); + QVERIFY(!(invalid >= c02)); + + QVERIFY(!(invalid == *m02)); + QVERIFY(invalid <= *m02); + QVERIFY(invalid < *m02); + QVERIFY(!(invalid > *m02)); + QVERIFY(!(invalid >= *m02)); + + QVERIFY(!(*m02 == invalid)); + QVERIFY(!(*m02 <= invalid)); + QVERIFY(!(*m02 < invalid)); + QVERIFY(*m02 > invalid); + QVERIFY(*m02 >= invalid); + + // MovingCursor <-> MovingCursor + QVERIFY(*m02 == *m02); + QVERIFY(*m02 <= *m02); + QVERIFY(*m02 >= *m02); + QVERIFY(!(*m02 < *m02)); + QVERIFY(!(*m02 > *m02)); + QVERIFY(!(*m02 != *m02)); + + QVERIFY(!(*m02 == *m04)); + QVERIFY(*m02 <= *m04); + QVERIFY(!(*m02 >= *m04)); + QVERIFY(*m02 < *m04); + QVERIFY(!(*m02 > *m04)); + QVERIFY(*m02 != *m04); + + QVERIFY(!(*m04 == *m02)); + QVERIFY(!(*m04 <= *m02)); + QVERIFY(*m04 >= *m02); + QVERIFY(!(*m04 < *m02)); + QVERIFY(*m04 > *m02); + QVERIFY(*m04 != *m02); + + QVERIFY(!(*m02 == *m14)); + QVERIFY(*m02 <= *m14); + QVERIFY(!(*m02 >= *m14)); + QVERIFY(*m02 < *m14); + QVERIFY(!(*m02 > *m14)); + QVERIFY(*m02 != *m14); + + QVERIFY(!(*m14 == *m02)); + QVERIFY(!(*m14 <= *m02)); + QVERIFY(*m14 >= *m02); + QVERIFY(!(*m14 < *m02)); + QVERIFY(*m14 > *m02); + QVERIFY(*m14 != *m02); + + // MovingCursor <-> Cursor + QVERIFY(*m02 == c02); + QVERIFY(*m02 <= c02); + QVERIFY(*m02 >= c02); + QVERIFY(!(*m02 < c02)); + QVERIFY(!(*m02 > c02)); + QVERIFY(!(*m02 != c02)); + + QVERIFY(!(*m02 == c04)); + QVERIFY(*m02 <= c04); + QVERIFY(!(*m02 >= c04)); + QVERIFY(*m02 < c04); + QVERIFY(!(*m02 > c04)); + QVERIFY(*m02 != c04); + + QVERIFY(!(*m04 == c02)); + QVERIFY(!(*m04 <= c02)); + QVERIFY(*m04 >= c02); + QVERIFY(!(*m04 < c02)); + QVERIFY(*m04 > c02); + QVERIFY(*m04 != c02); + + QVERIFY(!(*m02 == c14)); + QVERIFY(*m02 <= c14); + QVERIFY(!(*m02 >= c14)); + QVERIFY(*m02 < c14); + QVERIFY(!(*m02 > c14)); + QVERIFY(*m02 != c14); + + QVERIFY(!(*m14 == c02)); + QVERIFY(!(*m14 <= c02)); + QVERIFY(*m14 >= c02); + QVERIFY(!(*m14 < c02)); + QVERIFY(*m14 > c02); + QVERIFY(*m14 != c02); + + // Cursor <-> MovingCursor + QVERIFY(c02 == *m02); + QVERIFY(c02 <= *m02); + QVERIFY(c02 >= *m02); + QVERIFY(!(c02 < *m02)); + QVERIFY(!(c02 > *m02)); + QVERIFY(!(c02 != *m02)); + + QVERIFY(!(c02 == *m04)); + QVERIFY(c02 <= *m04); + QVERIFY(!(c02 >= *m04)); + QVERIFY(c02 < *m04); + QVERIFY(!(c02 > *m04)); + QVERIFY(c02 != *m04); + + QVERIFY(!(c04 == *m02)); + QVERIFY(!(c04 <= *m02)); + QVERIFY(c04 >= *m02); + QVERIFY(!(c04 < *m02)); + QVERIFY(c04 > *m02); + QVERIFY(c04 != *m02); + + QVERIFY(!(c02 == *m14)); + QVERIFY(c02 <= *m14); + QVERIFY(!(c02 >= *m14)); + QVERIFY(c02 < *m14); + QVERIFY(!(c02 > *m14)); + QVERIFY(c02 != *m14); + + QVERIFY(!(c14 == *m02)); + QVERIFY(!(c14 <= *m02)); + QVERIFY(c14 >= *m02); + QVERIFY(!(c14 < *m02)); + QVERIFY(c14 > *m02); + QVERIFY(c14 != *m02); +} diff --git a/share/tests/movingcursor_test.h b/share/tests/movingcursor_test.h new file mode 100644 index 0000000..03d814a --- /dev/null +++ b/share/tests/movingcursor_test.h @@ -0,0 +1,39 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_MOVINGCURSOR_TEST_H +#define KATE_MOVINGCURSOR_TEST_H + +#include + +class MovingCursorTest : public QObject +{ + Q_OBJECT + +public: + MovingCursorTest(); + ~MovingCursorTest(); + +private Q_SLOTS: + void testMovingCursor(); + void testConvenienceApi(); + void testOperators(); +}; + +#endif // KATE_MOVINGCURSOR_TEST_H diff --git a/share/tests/movingrange_test.cpp b/share/tests/movingrange_test.cpp new file mode 100644 index 0000000..774c531 --- /dev/null +++ b/share/tests/movingrange_test.cpp @@ -0,0 +1,425 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "movingrange_test.h" +#include "moc_movingrange_test.cpp" + +#include +#include + +#include +#include +#include +#include + +using namespace KTextEditor; + +QTEST_KDEMAIN(MovingRangeTest, GUI) + +namespace QTest { + template<> + char *toString(const KTextEditor::Cursor &cursor) + { + QByteArray ba = "Cursor[" + QByteArray::number(cursor.line()) + + ", " + QByteArray::number(cursor.column()) + "]"; + return qstrdup(ba.data()); + } +} + + +class RangeFeedback : public MovingRangeFeedback +{ + public: + RangeFeedback() : MovingRangeFeedback() { reset(); } + + virtual void rangeEmpty (MovingRange* range) { + m_rangeEmptyCalled = true; + } + + virtual void rangeInvalid (MovingRange* range) { + m_rangeInvalidCalled = true; + } + + virtual void mouseEnteredRange (MovingRange* range, View* view) { + m_mouseEnteredRangeCalled = true; + } + + virtual void mouseExitedRange (MovingRange* range, View* view) { + m_mouseExitedRangeCalled = true; + } + + virtual void caretEnteredRange (MovingRange* range, View* view) { + m_caretEnteredRangeCalled = true; + } + + virtual void caretExitedRange (MovingRange* range, View* view) { + m_caretExitedRangeCalled = true; + } + + // + // Test functions to reset feedback watcher + // + public: + void reset() { + m_rangeEmptyCalled = false; + m_rangeInvalidCalled = false; + m_mouseEnteredRangeCalled = false; + m_mouseExitedRangeCalled = false; + m_caretEnteredRangeCalled = false; + m_caretExitedRangeCalled = false; + } + + void verifyReset() { + QVERIFY(!m_rangeEmptyCalled); + QVERIFY(!m_rangeInvalidCalled); + QVERIFY(!m_mouseEnteredRangeCalled); + QVERIFY(!m_mouseExitedRangeCalled); + QVERIFY(!m_caretEnteredRangeCalled); + QVERIFY(!m_caretExitedRangeCalled); + } + + bool rangeEmptyCalled() const { return m_rangeEmptyCalled; } + bool rangeInvalidCalled() const { return m_rangeInvalidCalled; } + bool mouseEnteredRangeCalled() const { return m_mouseEnteredRangeCalled; } + bool mouseExitedRangeCalled() const { return m_mouseExitedRangeCalled; } + bool caretEnteredRangeCalled() const { return m_caretEnteredRangeCalled; } + bool caretExitedRangeCalled() const { return m_caretExitedRangeCalled; } + + private: + bool m_rangeEmptyCalled; + bool m_rangeInvalidCalled; + bool m_mouseEnteredRangeCalled; + bool m_mouseExitedRangeCalled; + bool m_caretEnteredRangeCalled; + bool m_caretExitedRangeCalled; +}; + + +MovingRangeTest::MovingRangeTest() + : QObject() +{ +} + +MovingRangeTest::~MovingRangeTest() +{ +} + +// tests: +// - RangeFeedback::rangeEmpty +void MovingRangeTest::testFeedbackEmptyRange() +{ + KateDocument doc (false, false, false); + // the range created below will span the 'x' characters + QString text("..xxxx\n" + "xxxx.."); + doc.setText(text); + + // create range feedback + RangeFeedback rf; + + // allow empty + MovingRange* range = doc.newMovingRange(Range(Cursor(0, 2), Cursor(1, 4)), + KTextEditor::MovingRange::DoNotExpand, + KTextEditor::MovingRange::AllowEmpty); + range->setFeedback(&rf); + rf.verifyReset(); + + // remove exact range + doc.removeText(range->toRange()); + QVERIFY(rf.rangeEmptyCalled()); + QVERIFY(!rf.rangeInvalidCalled()); + QVERIFY(!rf.mouseEnteredRangeCalled()); + QVERIFY(!rf.mouseExitedRangeCalled()); + QVERIFY(!rf.caretEnteredRangeCalled()); + QVERIFY(!rf.caretExitedRangeCalled()); + + // clear document: should call rangeInvalid + rf.reset(); + rf.verifyReset(); + doc.clear(); + QVERIFY(rf.rangeInvalidCalled()); + QVERIFY(!rf.rangeEmptyCalled()); + QVERIFY(!rf.mouseEnteredRangeCalled()); + QVERIFY(!rf.mouseExitedRangeCalled()); + QVERIFY(!rf.caretEnteredRangeCalled()); + QVERIFY(!rf.caretExitedRangeCalled()); + + // setText: should behave just like clear document: call rangeInvalid again + doc.setText(text); + range->setRange(Range(Cursor(0, 2), Cursor(1, 4))); + rf.reset(); + rf.verifyReset(); + doc.setText("--yyyy\nyyyy--"); + QVERIFY(rf.rangeInvalidCalled()); + QVERIFY(!rf.rangeEmptyCalled()); + QVERIFY(!rf.mouseEnteredRangeCalled()); + QVERIFY(!rf.mouseExitedRangeCalled()); + QVERIFY(!rf.caretEnteredRangeCalled()); + QVERIFY(!rf.caretExitedRangeCalled()); + + // now remove entire document range. In this case, emptyRange should be called + // instead of rangeInvalid + doc.setText(text); + range->setRange(Range(Cursor(0, 2), Cursor(1, 4))); + rf.reset(); + rf.verifyReset(); + doc.removeText(doc.documentRange()); + QVERIFY(rf.rangeEmptyCalled()); + QVERIFY(!rf.rangeInvalidCalled()); + QVERIFY(!rf.mouseEnteredRangeCalled()); + QVERIFY(!rf.mouseExitedRangeCalled()); + QVERIFY(!rf.caretEnteredRangeCalled()); + QVERIFY(!rf.caretExitedRangeCalled()); +} + +// tests: +// - RangeFeedback::rangeInvalid +void MovingRangeTest::testFeedbackInvalidRange() +{ + KateDocument doc (false, false, false); + // the range created below will span the 'x' characters + QString text("..xxxx\n" + "xxxx.."); + doc.setText(text); + + // create range feedback + RangeFeedback rf; + + // allow empty + MovingRange* range = doc.newMovingRange(Range(Cursor(0, 2), Cursor(1, 4)), + KTextEditor::MovingRange::DoNotExpand, + KTextEditor::MovingRange::InvalidateIfEmpty); + range->setFeedback(&rf); + rf.verifyReset(); + + // remove exact range + doc.removeText(range->toRange()); + QVERIFY(!rf.rangeEmptyCalled()); + QVERIFY(rf.rangeInvalidCalled()); + QVERIFY(!rf.mouseEnteredRangeCalled()); + QVERIFY(!rf.mouseExitedRangeCalled()); + QVERIFY(!rf.caretEnteredRangeCalled()); + QVERIFY(!rf.caretExitedRangeCalled()); + + // clear document: should call rangeInvalid again + doc.setText(text); + range->setRange(Range(Cursor(0, 2), Cursor(1, 4))); + rf.reset(); + rf.verifyReset(); + doc.clear(); + QVERIFY(rf.rangeInvalidCalled()); + QVERIFY(!rf.rangeEmptyCalled()); + QVERIFY(!rf.mouseEnteredRangeCalled()); + QVERIFY(!rf.mouseExitedRangeCalled()); + QVERIFY(!rf.caretEnteredRangeCalled()); + QVERIFY(!rf.caretExitedRangeCalled()); + + // setText: should behave just like clear document: call rangeInvalid again + doc.setText(text); + range->setRange(Range(Cursor(0, 2), Cursor(1, 4))); + rf.reset(); + rf.verifyReset(); + doc.setText("--yyyy\nyyyy--"); + QVERIFY(rf.rangeInvalidCalled()); + QVERIFY(!rf.rangeEmptyCalled()); + QVERIFY(!rf.mouseEnteredRangeCalled()); + QVERIFY(!rf.mouseExitedRangeCalled()); + QVERIFY(!rf.caretEnteredRangeCalled()); + QVERIFY(!rf.caretExitedRangeCalled()); + + // now remove entire document range. Call rangeInvalid again + doc.setText(text); + range->setRange(Range(Cursor(0, 2), Cursor(1, 4))); + rf.reset(); + rf.verifyReset(); + doc.removeText(doc.documentRange()); + QVERIFY(rf.rangeInvalidCalled()); + QVERIFY(!rf.rangeEmptyCalled()); + QVERIFY(!rf.mouseEnteredRangeCalled()); + QVERIFY(!rf.mouseExitedRangeCalled()); + QVERIFY(!rf.caretEnteredRangeCalled()); + QVERIFY(!rf.caretExitedRangeCalled()); +} + +// tests: +// - RangeFeedback::caretEnteredRange +// - RangeFeedback::caretExitedRange +void MovingRangeTest::testFeedbackCaret() +{ + KateDocument doc (false, false, false); + // the range created below will span the 'x' characters + QString text("..xxxx\n" + "xxxx.."); + doc.setText(text); + + KateView* view = static_cast(doc.createView(0)); + + // create range feedback + RangeFeedback rf; + + // first test: with ExpandLeft | ExpandRight + { + view->setCursorPosition(Cursor(1, 6)); + + MovingRange* range = doc.newMovingRange(Range(Cursor(0, 2), Cursor(1, 4)), + KTextEditor::MovingRange::ExpandLeft | + KTextEditor::MovingRange::ExpandRight, + KTextEditor::MovingRange::InvalidateIfEmpty); + rf.reset(); + range->setFeedback(&rf); + rf.verifyReset(); + + // left + view->cursorLeft(); + QCOMPARE(view->cursorPosition(), Cursor(1, 5)); + QVERIFY(!rf.caretEnteredRangeCalled()); + QVERIFY(!rf.caretExitedRangeCalled()); + + view->cursorLeft(); + QCOMPARE(view->cursorPosition(), Cursor(1, 4)); + QVERIFY(rf.caretEnteredRangeCalled()); // ExpandRight: include cursor already now + QVERIFY(!rf.caretExitedRangeCalled()); + + rf.reset(); + view->cursorLeft(); + QCOMPARE(view->cursorPosition(), Cursor(1, 3)); + QVERIFY(!rf.caretEnteredRangeCalled()); + QVERIFY(!rf.caretExitedRangeCalled()); + + rf.reset(); + view->up(); + QCOMPARE(view->cursorPosition(), Cursor(0, 3)); + QVERIFY(!rf.caretEnteredRangeCalled()); + QVERIFY(!rf.caretExitedRangeCalled()); + + rf.reset(); + view->cursorLeft(); + QCOMPARE(view->cursorPosition(), Cursor(0, 2)); + QVERIFY(!rf.caretEnteredRangeCalled()); + QVERIFY(!rf.caretExitedRangeCalled()); + + rf.reset(); + view->cursorLeft(); + QCOMPARE(view->cursorPosition(), Cursor(0, 1)); // ExpandLeft: now we left it, not before + QVERIFY(!rf.caretEnteredRangeCalled()); + QVERIFY(rf.caretExitedRangeCalled()); + + delete range; + } + + + // second test: with DoNotExpand + { + view->setCursorPosition(Cursor(1, 6)); + + MovingRange* range = doc.newMovingRange(Range(Cursor(0, 2), Cursor(1, 4)), + KTextEditor::MovingRange::DoNotExpand, + KTextEditor::MovingRange::InvalidateIfEmpty); + rf.reset(); + range->setFeedback(&rf); + rf.verifyReset(); + + // left + view->cursorLeft(); + QCOMPARE(view->cursorPosition(), Cursor(1, 5)); + QVERIFY(!rf.caretEnteredRangeCalled()); + QVERIFY(!rf.caretExitedRangeCalled()); + + view->cursorLeft(); + QCOMPARE(view->cursorPosition(), Cursor(1, 4)); + QVERIFY(!rf.caretEnteredRangeCalled()); // DoNotExpand: does not include cursor + QVERIFY(!rf.caretExitedRangeCalled()); + + rf.reset(); + view->cursorLeft(); + QCOMPARE(view->cursorPosition(), Cursor(1, 3)); + QVERIFY(rf.caretEnteredRangeCalled()); + QVERIFY(!rf.caretExitedRangeCalled()); + + rf.reset(); + view->up(); + QCOMPARE(view->cursorPosition(), Cursor(0, 3)); + QVERIFY(!rf.caretEnteredRangeCalled()); + QVERIFY(!rf.caretExitedRangeCalled()); + + rf.reset(); + view->cursorLeft(); + QCOMPARE(view->cursorPosition(), Cursor(0, 2)); + QVERIFY(!rf.caretEnteredRangeCalled()); + QVERIFY(rf.caretExitedRangeCalled()); // DoNotExpand: that's why we leave already now + + rf.reset(); + view->cursorLeft(); + QCOMPARE(view->cursorPosition(), Cursor(0, 1)); + QVERIFY(!rf.caretEnteredRangeCalled()); + QVERIFY(!rf.caretExitedRangeCalled()); + + delete range; + } +} + +// tests: +// - RangeFeedback::mouseEnteredRange +// - RangeFeedback::mouseExitedRange +void MovingRangeTest::testFeedbackMouse() +{ + KateDocument doc (false, false, false); + // the range created below will span the 'x' characters + QString text("..xxxx\n" + "xxxx.."); + doc.setText(text); + + KateView* view = static_cast(doc.createView(0)); + view->setCursorPosition(Cursor(1, 6)); + view->show(); + view->resize(200, 100); + + // create range feedback + RangeFeedback rf; + QVERIFY(!rf.mouseEnteredRangeCalled()); + QVERIFY(!rf.mouseExitedRangeCalled()); + + // allow empty + MovingRange* range = doc.newMovingRange(Range(Cursor(0, 2), Cursor(1, 4)), + KTextEditor::MovingRange::ExpandLeft | + KTextEditor::MovingRange::ExpandRight, + KTextEditor::MovingRange::InvalidateIfEmpty); + range->setFeedback(&rf); + rf.verifyReset(); + + // left (nothing) + QTest::mouseMove(view, view->cursorToCoordinate(Cursor(0, 0)) + QPoint(0, 5)); + QTest::qWait(200); // process mouse events. do not move mouse manually + QVERIFY(!rf.mouseEnteredRangeCalled()); + QVERIFY(!rf.mouseExitedRangeCalled()); + + // middle (enter) + rf.reset(); + QTest::mouseMove(view, view->cursorToCoordinate(Cursor(0, 3)) + QPoint(0, 5)); + QTest::qWait(200); // process mouse events. do not move mouse manually + QVERIFY(rf.mouseEnteredRangeCalled()); + QVERIFY(!rf.mouseExitedRangeCalled()); + + // right (exit) + rf.reset(); + QTest::mouseMove(view, view->cursorToCoordinate(Cursor(1, 6)) + QPoint(10, 5)); + QTest::qWait(200); // process mouse events. do not move mouse manually + QVERIFY(!rf.mouseEnteredRangeCalled()); + QVERIFY(rf.mouseExitedRangeCalled()); +} diff --git a/share/tests/movingrange_test.h b/share/tests/movingrange_test.h new file mode 100644 index 0000000..3b9eade --- /dev/null +++ b/share/tests/movingrange_test.h @@ -0,0 +1,40 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_MOVINGRANGE_TEST_H +#define KATE_MOVINGRANGE_TEST_H + +#include + +class MovingRangeTest : public QObject +{ + Q_OBJECT + +public: + MovingRangeTest(); + ~MovingRangeTest(); + +private Q_SLOTS: + void testFeedbackEmptyRange(); + void testFeedbackInvalidRange(); + void testFeedbackCaret(); + void testFeedbackMouse(); +}; + +#endif // KATE_MOVINGRANGE_TEST_H diff --git a/share/tests/plaintextsearch_test.cpp b/share/tests/plaintextsearch_test.cpp new file mode 100644 index 0000000..4ff5136 --- /dev/null +++ b/share/tests/plaintextsearch_test.cpp @@ -0,0 +1,181 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Bernhard Beschow + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "plaintextsearch_test.h" +#include "moc_plaintextsearch_test.cpp" + +#include + +#include +#include + +Q_DECLARE_METATYPE(KTextEditor::Range) + +QTEST_KDEMAIN(PlainTextSearchTest, GUI) + +namespace QTest { + template<> + char *toString(const KTextEditor::Range &range) + { + QByteArray ba = "Range["; + ba += QByteArray::number(range.start().line()) + ", " + QByteArray::number(range.start().column()) + ", "; + ba += QByteArray::number(range.end().line()) + ", " + QByteArray::number(range.end().column()); + ba += "]"; + return qstrdup(ba.data()); + } +} + +QtMsgHandler PlainTextSearchTest::s_msgHandler = 0; + +void myMessageOutput(QtMsgType type, const char *msg) +{ + switch (type) { + case QtDebugMsg: + /* do nothing */ + break; + default: + PlainTextSearchTest::s_msgHandler(type, msg); + } +} + +void PlainTextSearchTest::initTestCase() +{ + s_msgHandler = qInstallMsgHandler(myMessageOutput); +} + +void PlainTextSearchTest::cleanupTestCase() +{ + qInstallMsgHandler(0); +} + +PlainTextSearchTest::PlainTextSearchTest() + : QObject() + , m_doc(0) + , m_search(0) +{ +} + +PlainTextSearchTest::~PlainTextSearchTest() +{ +} + +void PlainTextSearchTest::init() +{ + m_doc = new KateDocument(false, false, false, 0, this); + m_search = new KatePlainTextSearch(m_doc, Qt::CaseSensitive, false); +} + +void PlainTextSearchTest::cleanup() +{ + delete m_search; + delete m_doc; +} + +void PlainTextSearchTest::testSearchBackward_data() +{ + QTest::addColumn("searchRange"); + QTest::addColumn("expectedResult"); + + QTest::newRow("") << KTextEditor::Range(0, 0, 1, 10) << KTextEditor::Range(1, 6, 1, 10); + QTest::newRow("") << KTextEditor::Range(0, 0, 1, 5) << KTextEditor::Range(1, 0, 1, 4); + QTest::newRow("") << KTextEditor::Range(0, 0, 1, 0) << KTextEditor::Range(0, 10, 0, 14); +} + +void PlainTextSearchTest::testSearchBackward() +{ + QFETCH(KTextEditor::Range, searchRange); + QFETCH(KTextEditor::Range, expectedResult); + + m_doc->setText("aaaa aaaa aaaa\n" + "aaaa aaaa"); + + QCOMPARE(m_search->search("aaaa", searchRange, true), expectedResult); +} + +void PlainTextSearchTest::testSingleLineDocument_data() +{ + QTest::addColumn("searchRange"); + QTest::addColumn("forwardResult"); + QTest::addColumn("backwardResult"); + + QTest::newRow("[a a a a a a a a a a a a]") << KTextEditor::Range(0, 0, 0, 23) << KTextEditor::Range(0, 0, 0, 5) << KTextEditor::Range(0, 18, 0, 23); + QTest::newRow("[a a a a a a a a a a a ]a") << KTextEditor::Range(0, 0, 0, 22) << KTextEditor::Range(0, 0, 0, 5) << KTextEditor::Range(0, 16, 0, 21); + QTest::newRow("a[ a a a a a a a a a a a]") << KTextEditor::Range(0, 1, 0, 23) << KTextEditor::Range(0, 2, 0, 7) << KTextEditor::Range(0, 18, 0, 23); + QTest::newRow("a[ a a a a a a a a a a ]a") << KTextEditor::Range(0, 1, 0, 22) << KTextEditor::Range(0, 2, 0, 7) << KTextEditor::Range(0, 16, 0, 21); + QTest::newRow("[a a a a] a a a a a a a a") << KTextEditor::Range(0, 0, 0, 7) << KTextEditor::Range(0, 0, 0, 5) << KTextEditor::Range(0, 2, 0, 7); + QTest::newRow("[a a a ]a a a a a a a a a") << KTextEditor::Range(0, 0, 0, 6) << KTextEditor::Range(0, 0, 0, 5) << KTextEditor::Range(0, 0, 0, 5); + QTest::newRow("[a a a] a a a a a a a a a") << KTextEditor::Range(0, 0, 0, 5) << KTextEditor::Range(0, 0, 0, 5) << KTextEditor::Range(0, 0, 0, 5); + QTest::newRow("[a a ]a a a a a a a a a a") << KTextEditor::Range(0, 0, 0, 4) << KTextEditor::Range::invalid() << KTextEditor::Range::invalid(); + QTest::newRow("a a a a a a a a [a a a a]") << KTextEditor::Range(0, 16, 0, 23) << KTextEditor::Range(0, 16, 0, 21) << KTextEditor::Range(0, 18, 0, 23); + QTest::newRow("a a a a a a a a a[ a a a]") << KTextEditor::Range(0, 17, 0, 23) << KTextEditor::Range(0, 18, 0, 23) << KTextEditor::Range(0, 18, 0, 23); + QTest::newRow("a a a a a a a a a [a a a]") << KTextEditor::Range(0, 18, 0, 23) << KTextEditor::Range(0, 18, 0, 23) << KTextEditor::Range(0, 18, 0, 23); + QTest::newRow("a a a a a a a a a a[ a a]") << KTextEditor::Range(0, 19, 0, 23) << KTextEditor::Range::invalid() << KTextEditor::Range::invalid(); + QTest::newRow("a a a a a[ a a a a] a a a") << KTextEditor::Range(0, 9, 0, 17) << KTextEditor::Range(0, 10, 0, 15) << KTextEditor::Range(0, 12, 0, 17); + QTest::newRow("a a a a a[ a a] a a a a a") << KTextEditor::Range(0, 9, 0, 13) << KTextEditor::Range::invalid() << KTextEditor::Range::invalid(); +} + +void PlainTextSearchTest::testSingleLineDocument() +{ + QFETCH(KTextEditor::Range, searchRange); + QFETCH(KTextEditor::Range, forwardResult); + QFETCH(KTextEditor::Range, backwardResult); + + m_doc->setText("a a a a a a a a a a a a"); + + QCOMPARE(m_search->search("a a a", searchRange, false), forwardResult); + QCOMPARE(m_search->search("a a a", searchRange, true), backwardResult); +} + +void PlainTextSearchTest::testMultilineSearch_data() +{ + QTest::addColumn("pattern"); + QTest::addColumn("inputRange"); + QTest::addColumn("forwardResult"); + + QTest::newRow("") << "a a a\na a\na a a" << KTextEditor::Range(0, 0, 2, 5) << KTextEditor::Range(0, 0, 2, 5); + QTest::newRow("") << "a a a\na a\na a " << KTextEditor::Range(0, 0, 2, 5) << KTextEditor::Range(0, 0, 2, 4); + QTest::newRow("") << "a a a\na a\na a" << KTextEditor::Range(0, 0, 2, 5) << KTextEditor::Range(0, 0, 2, 3); + QTest::newRow("") << "a a a\na a\na" << KTextEditor::Range(0, 0, 2, 5) << KTextEditor::Range(0, 0, 2, 1); + QTest::newRow("") << "a a a\na a\n" << KTextEditor::Range(0, 0, 2, 5) << KTextEditor::Range(0, 0, 2, 0); + QTest::newRow("") << "a a a\na a" << KTextEditor::Range(0, 0, 2, 5) << KTextEditor::Range(0, 0, 1, 3); + QTest::newRow("") << "a a\na a" << KTextEditor::Range(0, 0, 2, 5) << KTextEditor::Range(0, 2, 1, 3); + QTest::newRow("") << "a a\na a\na a" << KTextEditor::Range(0, 0, 2, 5) << KTextEditor::Range(0, 2, 2, 3); + QTest::newRow("") << "\na a\na a" << KTextEditor::Range(0, 0, 2, 5) << KTextEditor::Range(0, 5, 2, 3); + QTest::newRow("") << "\na a\n" << KTextEditor::Range(0, 0, 2, 5) << KTextEditor::Range(0, 5, 2, 0); + + QTest::newRow("") << "a a a\na a\na a a" << KTextEditor::Range(0, 0, 2, 4) << KTextEditor::Range::invalid(); + QTest::newRow("") << "a a a\na a\na a " << KTextEditor::Range(0, 0, 2, 4) << KTextEditor::Range(0, 0, 2, 4); + QTest::newRow("") << "a a a\na a\n" << KTextEditor::Range(0, 0, 2, 0) << KTextEditor::Range(0, 0, 2, 0); + QTest::newRow("") << "a a a\na a\n" << KTextEditor::Range(0, 0, 1, 3) << KTextEditor::Range::invalid(); + QTest::newRow("") << "a a\n" << KTextEditor::Range(0, 0, 1, 3) << KTextEditor::Range(0, 2, 1, 0); + QTest::newRow("") << "a \n" << KTextEditor::Range(0, 0, 1, 3) << KTextEditor::Range::invalid(); +} + +void PlainTextSearchTest::testMultilineSearch() +{ + QFETCH(QString, pattern); + QFETCH(KTextEditor::Range, inputRange); + QFETCH(KTextEditor::Range, forwardResult); + + m_doc->setText("a a a\n" + "a a\n" + "a a a"); + + QCOMPARE(m_search->search(pattern, inputRange, false), forwardResult); +} diff --git a/share/tests/plaintextsearch_test.h b/share/tests/plaintextsearch_test.h new file mode 100644 index 0000000..7b39ee5 --- /dev/null +++ b/share/tests/plaintextsearch_test.h @@ -0,0 +1,60 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Bernhard Beschow + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_PLAINTEXTSEARCH_TEST_H +#define KATE_PLAINTEXTSEARCH_TEST_H + +#include + +class KateDocument; +class KatePlainTextSearch; + +class PlainTextSearchTest : public QObject +{ + Q_OBJECT + + public: + PlainTextSearchTest(); + virtual ~PlainTextSearchTest(); + + private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + void init(); + void cleanup(); + + void testSearchBackward_data(); + void testSearchBackward(); + + void testSingleLineDocument_data(); + void testSingleLineDocument(); + + void testMultilineSearch_data(); + void testMultilineSearch(); + + private: + KateDocument *m_doc; + KatePlainTextSearch *m_search; + + public: + static QtMsgHandler s_msgHandler; +}; + +#endif diff --git a/share/tests/range_test.cpp b/share/tests/range_test.cpp new file mode 100644 index 0000000..8c2b1d3 --- /dev/null +++ b/share/tests/range_test.cpp @@ -0,0 +1,151 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Christoph Cullmann + Copyright (C) 2005 Hamish Rodda + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "range_test.h" +#include "moc_range_test.cpp" + +#include + +#include +#include +#include +#include +#include + +QTEST_KDEMAIN(RangeTest, GUI) + +namespace QTest { + template<> + char *toString(const KTextEditor::Range &range) + { + QByteArray ba = "Range["; + ba += QByteArray::number(range.start().line()) + ", " + QByteArray::number(range.start().column()) + ", "; + ba += QByteArray::number(range.end().line()) + ", " + QByteArray::number(range.end().column()); + ba += "]"; + return qstrdup(ba.data()); + } +} + +#define testNewRow() (QTest::newRow(QString("line %1").arg(__LINE__).toAscii().data())) + +RangeTest::RangeTest() + : QObject() +{ +} + +RangeTest::~RangeTest() +{ +} + +void RangeTest::rangeCheck ( KTextEditor::Range & valid ) +{ + QVERIFY(valid.isValid() && valid.start() <= valid.end()); + + KTextEditor::Cursor before(0,1), start(0,2), end(1,4), after(1,10); + + KTextEditor::Range result(start, end); + QVERIFY(valid.isValid() && valid.start() <= valid.end()); + + valid.setRange(start, end); + QVERIFY(valid.isValid() && valid.start() <= valid.end()); + QCOMPARE(valid, result); + + valid.setRange(end, start); + QVERIFY(valid.isValid() && valid.start() <= valid.end()); + QCOMPARE(valid, result); + + valid.start() = after; + QVERIFY(valid.isValid() && valid.start() <= valid.end()); + QCOMPARE(valid, KTextEditor::Range(after, after)); + + valid = result; + QCOMPARE(valid, result); + + valid.end() = before; + QVERIFY(valid.isValid() && valid.start() <= valid.end()); + QCOMPARE(valid, KTextEditor::Range(before, before)); +} + +void RangeTest::testTextEditorRange() +{ + // test simple range + KTextEditor::Range range; + rangeCheck (range); +} + +void RangeTest::testTextRange() +{ + // test text range + KateDocument doc (false, false, false); + KTextEditor::MovingRange *complexRange = doc.newMovingRange (KTextEditor::Range()); + KTextEditor::Range range = *complexRange; + rangeCheck (range); + delete complexRange; +} + +void RangeTest::testInsertText() +{ + KateDocument doc (false, false, false); + + // Multi-line insert + KTextEditor::MovingCursor* cursor1 = doc.newMovingCursor(KTextEditor::Cursor(), KTextEditor::MovingCursor::StayOnInsert); + KTextEditor::MovingCursor* cursor2 = doc.newMovingCursor(KTextEditor::Cursor(), KTextEditor::MovingCursor::MoveOnInsert); + + doc.insertText(KTextEditor::Cursor(), "Test Text\nMore Test Text"); + QCOMPARE(doc.documentEnd(), KTextEditor::Cursor(1,14)); + + QString text = doc.text(KTextEditor::Range(1,0,1,14)); + QCOMPARE(text, QString("More Test Text")); + + // Check cursors and ranges have moved properly + QCOMPARE(cursor1->toCursor(), KTextEditor::Cursor(0,0)); + QCOMPARE(cursor2->toCursor(), KTextEditor::Cursor(1,14)); + + KTextEditor::Cursor cursor3 = doc.endOfLine(1); + + // Set up a few more lines + doc.insertText(*cursor2, "\nEven More Test Text"); + QCOMPARE(doc.documentEnd(), KTextEditor::Cursor(2,19)); + QCOMPARE(cursor3, doc.endOfLine(1)); +} + +void RangeTest::testCornerCaseInsertion() +{ + KateDocument doc (false, false, false); + + // lock first revision + doc.lockRevision (0); + + KTextEditor::MovingRange* rangeEdit = doc.newMovingRange(KTextEditor::Range(0,0,0,0)); + QCOMPARE(rangeEdit->toRange(), KTextEditor::Range(0,0,0,0)); + + doc.insertText(KTextEditor::Cursor(0,0), "\n"); + QCOMPARE(rangeEdit->toRange(), KTextEditor::Range(1,0,1,0)); + + // test translate + KTextEditor::Range translateTest (0,0,0,0); + doc.transformRange (translateTest, KTextEditor::MovingRange::DoNotExpand, KTextEditor::MovingRange::AllowEmpty, 0); + QCOMPARE(translateTest, KTextEditor::Range(1,0,1,0)); + + // test translate reverse + KTextEditor::Range reverseTranslateTest (1,0,1,0); + doc.transformRange (reverseTranslateTest, KTextEditor::MovingRange::DoNotExpand, KTextEditor::MovingRange::AllowEmpty, -1, 0); + QCOMPARE(reverseTranslateTest, KTextEditor::Range(0,0,0,0)); +} diff --git a/share/tests/range_test.h b/share/tests/range_test.h new file mode 100644 index 0000000..abdf1e9 --- /dev/null +++ b/share/tests/range_test.h @@ -0,0 +1,46 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Christoph Cullmann + Copyright (C) 2005 Hamish Rodda + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_RANGE_TEST_H +#define KATE_RANGE_TEST_H + +#include + +#include + +class RangeTest : public QObject +{ + Q_OBJECT + +public: + RangeTest(); + ~RangeTest(); + +private Q_SLOTS: + void testTextEditorRange(); + void testTextRange(); + void testInsertText(); + void testCornerCaseInsertion(); + +private: + void rangeCheck ( KTextEditor::Range & valid ); +}; + +#endif diff --git a/share/tests/regexpsearch_test.cpp b/share/tests/regexpsearch_test.cpp new file mode 100644 index 0000000..943cf99 --- /dev/null +++ b/share/tests/regexpsearch_test.cpp @@ -0,0 +1,299 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Bernhard Beschow + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "regexpsearch_test.h" +#include "moc_regexpsearch_test.cpp" + +#include + +#include +#include + +Q_DECLARE_METATYPE(KTextEditor::Range) + +QTEST_KDEMAIN(RegExpSearchTest, GUI) + +namespace QTest { + template<> + char *toString(const KTextEditor::Range &range) + { + QByteArray ba = "Range["; + ba += QByteArray::number(range.start().line()) + ", " + QByteArray::number(range.start().column()) + ", "; + ba += QByteArray::number(range.end().line()) + ", " + QByteArray::number(range.end().column()); + ba += "]"; + return qstrdup(ba.data()); + } +} + +#define testNewRow() (QTest::newRow(QString("line %1").arg(__LINE__).toAscii().data())) + +using namespace KTextEditor; + +RegExpSearchTest::RegExpSearchTest() + : QObject() +{ +} + +RegExpSearchTest::~RegExpSearchTest() +{ +} + +void RegExpSearchTest::testReplaceEscapeSequences_data() +{ + QTest::addColumn("pattern"); + QTest::addColumn("expected"); + + testNewRow() << "\\" << "\\"; + testNewRow() << "\\0" << "0"; + testNewRow() << "\\00" << "00"; + testNewRow() << "\\000" << "000"; + testNewRow() << "\\0000" << QString(QChar(0)); + testNewRow() << "\\0377" << QString(QChar(0377)); + testNewRow() << "\\0378" << "0378"; + testNewRow() << "\\a" << "\a"; + testNewRow() << "\\f" << "\f"; + testNewRow() << "\\n" << "\n"; + testNewRow() << "\\r" << "\r"; + testNewRow() << "\\t" << "\t"; + testNewRow() << "\\v" << "\v"; + testNewRow() << "\\x" << "x"; + testNewRow() << "\\x0" << "x0"; + testNewRow() << "\\x00" << "x00"; + testNewRow() << "\\x000" << "x000"; + testNewRow() << "\\x0000" << QString(QChar(0x0000)); + testNewRow() << "\\x00000" << QString(QChar(0x0000) + '0'); + testNewRow() << "\\xaaaa" << QString(QChar(0xaaaa)); + testNewRow() << "\\xFFFF" << QString(QChar(0xFFFF)); + testNewRow() << "\\xFFFg" << "xFFFg"; +} + +void RegExpSearchTest::testReplaceEscapeSequences() +{ + QFETCH(QString, pattern); + QFETCH(QString, expected); + + const QString result1 = KateRegExpSearch::escapePlaintext(pattern); + const QString result2 = KateRegExpSearch::buildReplacement(pattern, QStringList(), 0); + + QCOMPARE(result1, expected); + QCOMPARE(result2, expected); +} + +void RegExpSearchTest::testReplacementReferences_data() +{ + QTest::addColumn("pattern"); + QTest::addColumn("expected"); + QTest::addColumn("capturedTexts"); + + testNewRow() << "\\0" << "b" << (QStringList() << "b"); + testNewRow() << "\\00" << "b0" << (QStringList() << "b"); + testNewRow() << "\\000" << "b00" << (QStringList() << "b"); + testNewRow() << "\\0000" << QString(QChar(0)) << (QStringList() << "b"); + testNewRow() << "\\1" << "1" << (QStringList() << "b"); + testNewRow() << "\\0" << "b" << (QStringList() << "b" << "c"); + testNewRow() << "\\1" << "c" << (QStringList() << "b" << "c"); +} + +void RegExpSearchTest::testReplacementReferences() +{ + QFETCH(QString, pattern); + QFETCH(QString, expected); + QFETCH(QStringList, capturedTexts); + + const QString result = KateRegExpSearch::buildReplacement(pattern, capturedTexts, 1); + + QCOMPARE(result, expected); +} + +void RegExpSearchTest::testReplacementCaseConversion_data() +{ + QTest::addColumn("pattern"); + QTest::addColumn("expected"); + + testNewRow() << "a\\Uaa" << "aAA"; + testNewRow() << "a\\UAa" << "aAA"; + testNewRow() << "a\\UaA" << "aAA"; + + testNewRow() << "a\\uaa" << "aAa"; + testNewRow() << "a\\uAa" << "aAa"; + testNewRow() << "a\\uaA" << "aAA"; + + testNewRow() << "A\\LAA" << "Aaa"; + testNewRow() << "A\\LaA" << "Aaa"; + testNewRow() << "A\\LAa" << "Aaa"; + + testNewRow() << "A\\lAA" << "AaA"; + testNewRow() << "A\\lAa" << "Aaa"; + testNewRow() << "A\\laA" << "AaA"; + + testNewRow() << "a\\EaA" << "aaA"; + testNewRow() << "A\\EAa" << "AAa"; +} + +void RegExpSearchTest::testReplacementCaseConversion() +{ + QFETCH(QString, pattern); + QFETCH(QString, expected); + + const QString result = KateRegExpSearch::buildReplacement(pattern, QStringList(), 1); + + QCOMPARE(result, expected); +} + +void RegExpSearchTest::testReplacementCounter_data() +{ + QTest::addColumn("pattern"); + QTest::addColumn("counter"); + QTest::addColumn("expected"); + + testNewRow() << "a\\#b" << 1 << "a1b"; + testNewRow() << "a\\#b" << 10 << "a10b"; + testNewRow() << "a\\#####b" << 1 << "a00001b"; +} + +void RegExpSearchTest::testReplacementCounter() +{ + QFETCH(QString, pattern); + QFETCH(int, counter); + QFETCH(QString, expected); + + const QString result = KateRegExpSearch::buildReplacement(pattern, QStringList(), counter); + + QCOMPARE(result, expected); +} + +void RegExpSearchTest::testAnchoredRegexp_data() +{ + QTest::addColumn("pattern"); + QTest::addColumn("inputRange"); + QTest::addColumn("backwards"); + QTest::addColumn("expected"); + + testNewRow() << "fe" << Range(0, 0, 0, 8) << false << Range(0, 0, 0, 2); + testNewRow() << "fe" << Range(0, 0, 0, 8) << true << Range(0, 6, 0, 8); + + testNewRow() << "^fe" << Range(0, 0, 0, 8) << false << Range(0, 0, 0, 2); + testNewRow() << "^fe" << Range(0, 0, 0, 1) << false << Range::invalid(); + testNewRow() << "^fe" << Range(0, 0, 0, 2) << false << Range(0, 0, 0, 2); + testNewRow() << "^fe" << Range(0, 3, 0, 8) << false << Range::invalid(); // only match at line start + testNewRow() << "^fe" << Range(0, 0, 0, 2) << true << Range(0, 0, 0, 2); + testNewRow() << "^fe" << Range(0, 0, 0, 1) << true << Range::invalid(); + testNewRow() << "^fe" << Range(0, 0, 0, 2) << true << Range(0, 0, 0, 2); + testNewRow() << "^fe" << Range(0, 3, 0, 8) << true << Range::invalid(); + + testNewRow() << "fe$" << Range(0, 0, 0, 8) << false << Range(0, 6, 0, 8); + testNewRow() << "fe$" << Range(0, 7, 0, 8) << false << Range::invalid(); + testNewRow() << "fe$" << Range(0, 6, 0, 8) << false << Range(0, 6, 0, 8); +// testNewRow() << "fe$" << Range(0, 0, 0, 5) << false << Range::invalid(); // only match at line end, fails + testNewRow() << "fe$" << Range(0, 0, 0, 8) << true << Range(0, 6, 0, 8); + testNewRow() << "fe$" << Range(0, 7, 0, 8) << true << Range::invalid(); + testNewRow() << "fe$" << Range(0, 6, 0, 8) << true << Range(0, 6, 0, 8); +// testNewRow() << "fe$" << Range(0, 0, 0, 5) << true << Range::invalid(); // fails due to $-shortcoming in QRegExp + + testNewRow() << "^fe fe fe$" << Range(0, 0, 0, 8) << false << Range(0, 0, 0, 8); + testNewRow() << "^fe fe fe$" << Range(0, 3, 0, 8) << false << Range::invalid(); + testNewRow() << "^fe fe fe$" << Range(0, 0, 0, 5) << false << Range::invalid(); + testNewRow() << "^fe fe fe$" << Range(0, 3, 0, 5) << false << Range::invalid(); + testNewRow() << "^fe fe fe$" << Range(0, 0, 0, 8) << true << Range(0, 0, 0, 8); + testNewRow() << "^fe fe fe$" << Range(0, 3, 0, 8) << true << Range::invalid(); + testNewRow() << "^fe fe fe$" << Range(0, 0, 0, 5) << true << Range::invalid(); + testNewRow() << "^fe fe fe$" << Range(0, 3, 0, 5) << true << Range::invalid(); + + testNewRow() << "^fe( fe)*$" << Range(0, 0, 0, 8) << false << Range(0, 0, 0, 8); + testNewRow() << "^fe( fe)*" << Range(0, 0, 0, 8) << false << Range(0, 0, 0, 8); + testNewRow() << "fe( fe)*$" << Range(0, 0, 0, 8) << false << Range(0, 0, 0, 8); + testNewRow() << "fe( fe)*" << Range(0, 0, 0, 8) << false << Range(0, 0, 0, 8); + testNewRow() << "^fe( fe)*$" << Range(0, 3, 0, 8) << false << Range::invalid(); + testNewRow() << "fe( fe)*$" << Range(0, 3, 0, 8) << false << Range(0, 3, 0, 8); +// testNewRow() << "^fe( fe)*$" << Range(0, 0, 0, 5) << false << Range::invalid(); // fails due to $-shortcoming in QRegExp + testNewRow() << "^fe( fe)*" << Range(0, 0, 0, 5) << false << Range(0, 0, 0, 5); + testNewRow() << "^fe( fe)*$" << Range(0, 0, 0, 8) << true << Range(0, 0, 0, 8); + testNewRow() << "^fe( fe)*" << Range(0, 0, 0, 8) << true << Range(0, 0, 0, 8); +// testNewRow() << "fe( fe)*$" << Range(0, 0, 0, 8) << true << Range(0, 0, 0, 8); // fails, shouldn't matching be greedy? +// testNewRow() << "fe( fe)*" << Range(0, 0, 0, 8) << true << Range(0, 0, 0, 8); // fails, shouldn't matching be greedy? + testNewRow() << "^fe( fe)*$" << Range(0, 3, 0, 8) << true << Range::invalid(); +// testNewRow() << "fe( fe)*$" << Range(0, 3, 0, 8) << true << Range(0, 3, 0, 8); // fails, shouldn't matching be greedy? +// testNewRow() << "^fe( fe)*$" << Range(0, 0, 0, 5) << true << Range::invalid(); // fails due to $-shortcoming in QRegExp + + testNewRow() << "^fe|fe$" << Range(0, 0, 0, 5) << false << Range(0, 0, 0, 2); + testNewRow() << "^fe|fe$" << Range(0, 3, 0, 8) << false << Range(0, 6, 0, 8); +// testNewRow() << "^fe|fe$" << Range(0, 0, 0, 5) << true << Range(0, 0, 0, 2); // fails due to $-shortcoming in QRegExp + testNewRow() << "^fe|fe$" << Range(0, 3, 0, 8) << true << Range(0, 6, 0, 8); +} + +void RegExpSearchTest::testAnchoredRegexp() +{ + QFETCH(QString, pattern); + QFETCH(Range, inputRange); + QFETCH(bool, backwards); + QFETCH(Range, expected); + + KateDocument doc(false, false, false); + doc.setText("fe fe fe"); + + KateRegExpSearch searcher(&doc, Qt::CaseInsensitive); + + static int i = 0; + if (i == 34 || i == 36) + qDebug() << i; + i++; + + const Range result = searcher.search(pattern, inputRange, backwards)[0]; + + QCOMPARE(result, expected); +} + +void RegExpSearchTest::testSearchForward() +{ + KateDocument doc(false, false, false); + doc.setText(" \\piinfercong"); + + KateRegExpSearch search(&doc, Qt::CaseSensitive); + const Range result = search.search("\\\\piinfer(\\w)", Range(0, 2, 0, 15))[0]; + + QCOMPARE(result, Range(0, 2, 0, 11)); +} + +void RegExpSearchTest::testSearchBackwardInSelection() +{ + KateDocument doc(false, false, false); + doc.setText("foobar foo bar foo bar foo"); + + KateRegExpSearch search(&doc, Qt::CaseSensitive); + const Range result = search.search("foo", Range(0, 0, 0, 15), true)[0]; + + QCOMPARE(result, Range(0, 7, 0, 10)); +} + +void RegExpSearchTest::test() +{ + KateDocument doc(false, false, false); + doc.setText("\\newcommand{\\piReductionOut}"); + + KateRegExpSearch search(&doc, Qt::CaseSensitive); + const QVector result = search.search("\\\\piReduction(\\S)", Range(0, 10, 0, 28), true); + + QCOMPARE(result.size(), 2); + QCOMPARE(result[0], Range(0, 12, 0, 25)); + QCOMPARE(result[1], Range(0, 24, 0, 25)); + QCOMPARE(doc.text(result[0]), QString("\\piReductionO")); + QCOMPARE(doc.text(result[1]), QString("O")); +} + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/share/tests/regexpsearch_test.h b/share/tests/regexpsearch_test.h new file mode 100644 index 0000000..967da4a --- /dev/null +++ b/share/tests/regexpsearch_test.h @@ -0,0 +1,58 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Bernhard Beschow + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_REGEXPSEARCH_TEST_H +#define KATE_REGEXPSEARCH_TEST_H + +#include + +class RegExpSearchTest : public QObject +{ + Q_OBJECT + + public: + RegExpSearchTest(); + virtual ~RegExpSearchTest(); + + private Q_SLOTS: + void testReplaceEscapeSequences_data(); + void testReplaceEscapeSequences(); + + void testReplacementReferences_data(); + void testReplacementReferences(); + + void testReplacementCaseConversion_data(); + void testReplacementCaseConversion(); + + void testReplacementCounter_data(); + void testReplacementCounter(); + + void testAnchoredRegexp_data(); + void testAnchoredRegexp(); + + void testSearchForward(); + + void testSearchBackwardInSelection(); + + void test(); +}; + +#endif + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/share/tests/revision_test.cpp b/share/tests/revision_test.cpp new file mode 100644 index 0000000..c9830f2 --- /dev/null +++ b/share/tests/revision_test.cpp @@ -0,0 +1,180 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "revision_test.h" +#include "moc_revision_test.cpp" + +#include + +#include +#include +#include +#include + +using namespace KTextEditor; + +QTEST_KDEMAIN(RevisionTest, GUI) + +namespace QTest { + template<> + char *toString(const KTextEditor::Cursor &cursor) + { + QByteArray ba = "Cursor[" + QByteArray::number(cursor.line()) + + ", " + QByteArray::number(cursor.column()) + "]"; + return qstrdup(ba.data()); + } + + template<> + char *toString(const KTextEditor::Range &range) + { + QByteArray ba = "Range[" + QByteArray::number(range.start().line()) + + ", " + QByteArray::number(range.start().column()) + " - " + + QByteArray::number(range.end().line()) + + ", " + QByteArray::number(range.end().column()) + "]"; + return qstrdup(ba.data()); + } +} + + +RevisionTest::RevisionTest() + : QObject() +{ +} + +RevisionTest::~RevisionTest() +{ +} + +// tests: MovingInterface +// - lockRevision() +// - revision() +// - unlockRevision() +// - transformCursor() +void RevisionTest::testTransformCursor() +{ + KateDocument doc (false, false, false); + + // initial saved revision of unsaved document is -1 + QVERIFY(doc.lastSavedRevision() == -1); + + // initial revision is always 0 + QCOMPARE(doc.revision(), (qint64) 0); + + // one edit action -> revision now 1, last saved still -1 + doc.insertText(Cursor(0, 0), "0000"); + + qint64 rev = doc.revision(); + QCOMPARE(rev, (qint64) 1); + + // now lock current revision 1 + doc.lockRevision(rev); + + // wrapLine + insertText + wrapLine + insertText + doc.insertText(Cursor(0, 2), "\n1111\n2222"); + + // create some cursors, then transform them + Cursor c01(0, 1); + Cursor stayOnInsert(0, 2); + Cursor moveOnInsert(0, 2); + + doc.transformCursor(c01, MovingCursor::MoveOnInsert, rev, -1); + doc.transformCursor(moveOnInsert, MovingCursor::MoveOnInsert, rev, -1); + doc.transformCursor(stayOnInsert, MovingCursor::StayOnInsert, rev, -1); + + QCOMPARE(c01, Cursor(0, 1)); + QCOMPARE(stayOnInsert, Cursor(0, 2)); + QCOMPARE(moveOnInsert, Cursor(2, 4)); + + + // free revision and lock current again + doc.unlockRevision(rev); + rev = doc.revision(); + doc.lockRevision(rev); + + // now undo, the cursors should move to original positions again + doc.undo(); + + // inverse transformation + doc.transformCursor(c01, MovingCursor::MoveOnInsert, rev, -1); + doc.transformCursor(moveOnInsert, MovingCursor::MoveOnInsert, rev, -1); + doc.transformCursor(stayOnInsert, MovingCursor::StayOnInsert, rev, -1); + + QCOMPARE(c01, Cursor(0, 1)); + QCOMPARE(stayOnInsert, Cursor(0, 2)); + QCOMPARE(moveOnInsert, Cursor(0, 2)); +} + + +// tests: +// - transformRange() +void RevisionTest::testTransformRange() +{ + KateDocument doc (false, false, false); + + QCOMPARE(doc.revision(), (qint64) 0); + + doc.setText("00\n" + "11"); + + // now lock current revision + qint64 rev = doc.revision(); + doc.lockRevision(rev); + + + Range r1(Cursor(0, 0), Cursor(1, 2)); + Range r2(Cursor(0, 1), Cursor(1, 1)); + Range invalidOnEmpty(Cursor(0, 1), Cursor(1, 1)); + + // remove text + doc.removeText(Range(Cursor(0, 0), Cursor(1, 2))); + + doc.transformRange(r1, MovingRange::ExpandLeft | MovingRange::ExpandRight, + MovingRange::AllowEmpty, rev, -1); + doc.transformRange(r2, MovingRange::ExpandLeft | MovingRange::ExpandRight, + MovingRange::AllowEmpty, rev, -1); + doc.transformRange(invalidOnEmpty, MovingRange::ExpandLeft | MovingRange::ExpandRight, + MovingRange::InvalidateIfEmpty, rev, -1); + + + QCOMPARE(r1, Range(Cursor(0, 0), Cursor(0, 0))); + QCOMPARE(r2, Range(Cursor(0, 0), Cursor(0, 0))); + QCOMPARE(invalidOnEmpty, Range::invalid()); + + // free revision and lock current again + doc.unlockRevision(rev); + rev = doc.revision(); + doc.lockRevision(rev); + + // now undo + doc.undo(); + + // r1 should span the entire document + // r2 should be empty at end of document + // invalidOnEmpty should stay invalid + doc.transformRange(r1, MovingRange::ExpandLeft | MovingRange::ExpandRight, + MovingRange::AllowEmpty, rev, -1); + doc.transformRange(r2, MovingRange::ExpandRight, + MovingRange::AllowEmpty, rev, -1); + doc.transformRange(invalidOnEmpty, MovingRange::ExpandLeft | MovingRange::ExpandRight, + MovingRange::AllowEmpty, rev, -1); + + QCOMPARE(r1, Range(Cursor(0, 0), Cursor(1, 2))); + QCOMPARE(r2, Range(Cursor(1, 2), Cursor(1, 2))); + QCOMPARE(invalidOnEmpty, Range::invalid()); +} diff --git a/share/tests/revision_test.h b/share/tests/revision_test.h new file mode 100644 index 0000000..f786918 --- /dev/null +++ b/share/tests/revision_test.h @@ -0,0 +1,38 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_REVISION_TEST_H +#define KATE_REVISION_TEST_H + +#include + +class RevisionTest : public QObject +{ + Q_OBJECT + +public: + RevisionTest(); + ~RevisionTest(); + +private Q_SLOTS: + void testTransformCursor(); + void testTransformRange(); +}; + +#endif // KATE_REVISION_TEST_H diff --git a/share/tests/sands_indentation_test.cpp b/share/tests/sands_indentation_test.cpp new file mode 100644 index 0000000..a0bf38b --- /dev/null +++ b/share/tests/sands_indentation_test.cpp @@ -0,0 +1,67 @@ +// C++ S&S Indentation test. +// Copy this into kate and check that it indents corrently. +// Obviously that will be different for the different indentors, but this tries +// to check cases that I might not have thought of. +// TODO: Automate testing once the indentation actually works! + + +namespace Test +{ + +enum +{ + one, + two, + three, + four +}; + +bool function(int a, bool b, + int c, double d) +{ + for (int i = 0; i < b ? a : c; ++i) + cout << "Number: " << i << endl; + + switch (classType) + { + case '1': + case '/': + case ';': + break; + case ':': + colon: + break; + + case Test::one: + goto colon; + } + return Test::two; +} + +} + +class QWidget : public QObject +{ + Q_OBJECT +public: + QWidget() : parent(null) + { + } +private: + struct Car : Vehicle + { + + }; + +private slots: + Car test(); +} + +Car QWidget::test() +{ + // A comment. + cerr << "this" + << "is" << "a" << "test"; + /* A block + comment */ +} diff --git a/share/tests/scriptdocument_test.cpp b/share/tests/scriptdocument_test.cpp new file mode 100644 index 0000000..fc5c5e2 --- /dev/null +++ b/share/tests/scriptdocument_test.cpp @@ -0,0 +1,139 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Bernhard Beschow + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "scriptdocument_test.h" +#include "moc_scriptdocument_test.cpp" + +#include + +#include + +#include +#include + +Q_DECLARE_METATYPE(KTextEditor::Cursor) + +QTEST_KDEMAIN(ScriptDocumentTest, GUI) + +namespace QTest { + template<> + char *toString(const KTextEditor::Cursor &cursor) + { + QByteArray ba = "Cursor["; + ba += QByteArray::number(cursor.line()) + ", " + QByteArray::number(cursor.column()); + ba += "]"; + return qstrdup(ba.data()); + } +} + +QtMsgHandler ScriptDocumentTest::s_msgHandler = 0; + +void myMessageOutput(QtMsgType type, const char *msg) +{ + switch (type) { + case QtDebugMsg: + /* do nothing */ + break; + default: + ScriptDocumentTest::s_msgHandler(type, msg); + } +} + +void ScriptDocumentTest::initTestCase() +{ + s_msgHandler = qInstallMsgHandler(myMessageOutput); +} + +void ScriptDocumentTest::cleanupTestCase() +{ + qInstallMsgHandler(0); +} + +ScriptDocumentTest::ScriptDocumentTest() + : QObject() + , m_doc(0) + , m_view(0) + , m_scriptDoc(0) +{ +} + +ScriptDocumentTest::~ScriptDocumentTest() +{ +} + +void ScriptDocumentTest::init() +{ + m_doc = new KateDocument(false, false, false, 0, this); + m_view = m_doc->createView(0); + m_scriptDoc = new KateScriptDocument(this); + m_scriptDoc->setDocument(m_doc); +} + +void ScriptDocumentTest::cleanup() +{ + delete m_scriptDoc; + delete m_view; + delete m_doc; +} + +#if 0 +void ScriptDocumentTest::testRfind_data() +{ + QTest::addColumn("searchRange"); + QTest::addColumn("expectedResult"); + + QTest::newRow("") << KTextEditor::Range(0, 0, 1, 10) << KTextEditor::Range(1, 6, 1, 10); + QTest::newRow("") << KTextEditor::Range(0, 0, 1, 5) << KTextEditor::Range(1, 0, 1, 4); + QTest::newRow("") << KTextEditor::Range(0, 0, 1, 0) << KTextEditor::Range(0, 10, 0, 14); +} + +void ScriptDocumentTest::testRfind() +{ + QFETCH(KTextEditor::Range, searchRange); + QFETCH(KTextEditor::Range, expectedResult); + + m_doc->setText("aaaa aaaa aaaa\n" + "aaaa aaaa"); + + QCOMPARE(m_search->search(searchRange, "aaaa", true), expectedResult); +} +#endif + +void ScriptDocumentTest::testRfind_data() +{ + QTest::addColumn("searchStart"); + QTest::addColumn("result"); + + QTest::newRow("a a a a a a a a a a a a|") << KTextEditor::Cursor(0, 23) << KTextEditor::Cursor(0, 18); + QTest::newRow("a a a a a a a a a a a |a") << KTextEditor::Cursor(0, 22) << KTextEditor::Cursor(0, 16); + QTest::newRow("a a a a| a a a a a a a a") << KTextEditor::Cursor(0, 7) << KTextEditor::Cursor(0, 2); + QTest::newRow("a a a |a a a a a a a a a") << KTextEditor::Cursor(0, 6) << KTextEditor::Cursor(0, 0); + QTest::newRow("a a a| a a a a a a a a a") << KTextEditor::Cursor(0, 5) << KTextEditor::Cursor(0, 0); + QTest::newRow("a a |a a a a a a a a a a") << KTextEditor::Cursor(0, 4) << KTextEditor::Cursor::invalid(); +} + +void ScriptDocumentTest::testRfind() +{ + QFETCH(KTextEditor::Cursor, searchStart); + QFETCH(KTextEditor::Cursor, result); + + m_scriptDoc->setText("a a a a a a a a a a a a"); + + QCOMPARE(m_scriptDoc->rfind(searchStart.line(), searchStart.column(), "a a a"), result); +} diff --git a/share/tests/scriptdocument_test.h b/share/tests/scriptdocument_test.h new file mode 100644 index 0000000..df5b9be --- /dev/null +++ b/share/tests/scriptdocument_test.h @@ -0,0 +1,59 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Bernhard Beschow + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_SCRIPTDOCUMENT_TEST_H +#define KATE_SCRIPTDOCUMENT_TEST_H + +#include + +namespace KTextEditor { + class View; +} + +class KateDocument; +class KateScriptDocument; + +class ScriptDocumentTest : public QObject +{ + Q_OBJECT + + public: + ScriptDocumentTest(); + virtual ~ScriptDocumentTest(); + + private Q_SLOTS: + void initTestCase(); + void cleanupTestCase(); + + void init(); + void cleanup(); + + void testRfind_data(); + void testRfind(); + + private: + KateDocument *m_doc; + KTextEditor::View *m_view; + KateScriptDocument *m_scriptDoc; + + public: + static QtMsgHandler s_msgHandler; +}; + +#endif diff --git a/share/tests/searchbar_test.cpp b/share/tests/searchbar_test.cpp new file mode 100644 index 0000000..0d104a8 --- /dev/null +++ b/share/tests/searchbar_test.cpp @@ -0,0 +1,613 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Bernhard Beschow + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "searchbar_test.h" +#include "moc_searchbar_test.cpp" + +#include "ui_searchbarincremental.h" +#include "ui_searchbarpower.h" + +#include + +#include +#include +#include +#include +#include + +QTEST_KDEMAIN(SearchBarTest, GUI) + +namespace QTest { + template<> + char *toString(const KTextEditor::Range &range) + { + QByteArray ba = "Range["; + ba += QByteArray::number(range.start().line()) + ", " + QByteArray::number(range.start().column()) + ", "; + ba += QByteArray::number(range.end().line()) + ", " + QByteArray::number(range.end().column()); + ba += "]"; + return qstrdup(ba.data()); + } +} + +#define testNewRow() (QTest::newRow(QString("line %1").arg(__LINE__).toAscii().data())) + + +using namespace KTextEditor; + + +SearchBarTest::SearchBarTest() + : QObject() +{ +} + +SearchBarTest::~SearchBarTest() +{ +} + + +void SearchBarTest::testFindNextIncremental() +{ + KateDocument doc(false, false, false); + doc.setText("a a a b b"); + + KateView view(&doc, 0); + KateViewConfig config(&view); + + KateSearchBar bar(false, &view, &config); + + bar.setSearchPattern("b"); + + QCOMPARE(view.selectionRange(), Range(0, 6, 0, 7)); + + bar.findNext(); + + QCOMPARE(view.selectionRange(), Range(0, 8, 0, 9)); + + bar.setSearchPattern("a"); + + QCOMPARE(view.selectionRange(), Range(0, 0, 0, 1)); + + bar.findNext(); + + QCOMPARE(view.selectionRange(), Range(0, 2, 0, 3)); + + bar.findNext(); + + QCOMPARE(view.selectionRange(), Range(0, 4, 0, 5)); + + bar.findNext(); + + QCOMPARE(view.selectionRange(), Range(0, 0, 0, 1)); +} + + +void SearchBarTest::testSetMatchCaseIncremental() +{ + KateDocument doc(false, false, false); + KateView view(&doc, 0); + KateViewConfig config(&view); + + doc.setText("a A a"); + KateSearchBar bar(false, &view, &config); + + QVERIFY(!bar.isPower()); + QVERIFY(!view.selection()); + + bar.setMatchCase(false); + bar.setSearchPattern("A"); + + QVERIFY(!bar.matchCase()); + QCOMPARE(view.selectionRange(), Range(0, 0, 0, 1)); + + bar.setMatchCase(true); + + QVERIFY(bar.matchCase()); + QCOMPARE(view.selectionRange(), Range(0, 2, 0, 3)); + + bar.setMatchCase(false); + + QVERIFY(!bar.matchCase()); + QCOMPARE(view.selectionRange(), Range(0, 0, 0, 1)); + + bar.setMatchCase(true); + + QVERIFY(bar.matchCase()); + QCOMPARE(view.selectionRange(), Range(0, 2, 0, 3)); +} + + +void SearchBarTest::testSetMatchCasePower() +{ + KateDocument doc(false, false, false); + KateView view(&doc, 0); + KateViewConfig config(&view); + + doc.setText("a A a"); + view.setCursorPosition(Cursor(0, 0)); + + KateSearchBar bar(true, &view, &config); + + QVERIFY(bar.isPower()); + QVERIFY(!view.selection()); + + bar.setMatchCase(false); + bar.setSearchPattern("A"); + bar.findNext(); + + QCOMPARE(bar.searchPattern(), QString("A")); + QVERIFY(!bar.matchCase()); + QCOMPARE(view.selectionRange(), Range(0, 0, 0, 1)); + + bar.setMatchCase(true); + + QCOMPARE(view.selectionRange(), Range(0, 0, 0, 1)); + + bar.findNext(); + + QVERIFY(bar.matchCase()); + QCOMPARE(view.selectionRange(), Range(0, 2, 0, 3)); + + bar.setMatchCase(false); + + QVERIFY(!bar.matchCase()); + QCOMPARE(view.selectionRange(), Range(0, 2, 0, 3)); + + bar.findNext(); + + QCOMPARE(view.selectionRange(), Range(0, 4, 0, 5)); +} + + + +void SearchBarTest::testSetSelectionOnlyPower() +{ + KateDocument doc(false, false, false); + KateView view(&doc, 0); + KateViewConfig config(&view); + + doc.setText("a a a"); + KateSearchBar bar(true, &view, &config); + + bar.setSearchPattern("a"); + + QVERIFY(bar.isPower()); + QVERIFY(!view.selection()); + + bar.setSelectionOnly(false); + bar.findNext(); + + QVERIFY(!bar.selectionOnly()); + QCOMPARE(view.selectionRange(), Range(0, 0, 0, 1)); + + view.setSelection(Range(0, 2, 0, 5)); + bar.setSelectionOnly(true); + + QVERIFY(bar.selectionOnly()); + + bar.findNext(); + + QCOMPARE(view.selectionRange(), Range(0, 2, 0, 3)); + QVERIFY(bar.selectionOnly()); + + bar.setSelectionOnly(false); + bar.findNext(); + + QCOMPARE(view.selectionRange(), Range(0, 4, 0, 5)); + QVERIFY(!bar.selectionOnly()); +} + + +void SearchBarTest::testSetSearchPattern_data() +{ + QTest::addColumn("power"); + QTest::addColumn("numMatches2"); + + testNewRow() << false << 0; + testNewRow() << true << 3; +} + + +void SearchBarTest::testSetSearchPattern() +{ + QFETCH(bool, power); + QFETCH(int, numMatches2); + + KateDocument doc(false, false, false); + KateView view(&doc, 0); + KateViewConfig config(&view); + + doc.setText("a a a"); + + KateSearchBar bar(power, &view, &config); + + bar.setSearchPattern("a"); + bar.findAll(); + + QCOMPARE(bar.m_hlRanges.size(), 3); + + bar.setSearchPattern("a "); + + QCOMPARE(bar.m_hlRanges.size(), numMatches2); + + bar.findAll(); + + QCOMPARE(bar.m_hlRanges.size(), 2); +} + + +void SearchBarTest::testSetSelectionOnly() +{ + KateDocument doc(false, false, false); + KateView view(&doc, 0); + KateViewConfig config(&view); + + doc.setText("a a a"); + view.setSelection(Range(0, 0, 0, 3)); + + KateSearchBar bar(false, &view, &config); + + bar.setSelectionOnly(false); + bar.setSearchPattern("a"); + bar.findAll(); + + QCOMPARE(bar.m_hlRanges.size(), 3); + + bar.setSelectionOnly(true); + + QCOMPARE(bar.m_hlRanges.size(), 3); +} + + +void SearchBarTest::testFindAll_data() +{ + QTest::addColumn("power"); + QTest::addColumn("numMatches2"); + QTest::addColumn("numMatches4"); + + testNewRow() << false << 0 << 0; + testNewRow() << true << 3 << 2; +} + + +void SearchBarTest::testFindAll() +{ + QFETCH(bool, power); + QFETCH(int, numMatches2); + QFETCH(int, numMatches4); + + KateDocument doc(false, false, false); + KateView view(&doc, 0); + KateViewConfig config(&view); + + doc.setText("a a a"); + KateSearchBar bar(power, &view, &config); + + QCOMPARE(bar.isPower(), power); + + bar.setSearchPattern("a"); + bar.findAll(); + + QCOMPARE(bar.m_hlRanges.size(), 3); + QCOMPARE(bar.m_hlRanges.at(0)->toRange(), Range(0, 0, 0, 1)); + QCOMPARE(bar.m_hlRanges.at(1)->toRange(), Range(0, 2, 0, 3)); + QCOMPARE(bar.m_hlRanges.at(2)->toRange(), Range(0, 4, 0, 5)); + + bar.setSearchPattern("a "); + + QCOMPARE(bar.m_hlRanges.size(), numMatches2); + + bar.findAll(); + + QCOMPARE(bar.m_hlRanges.size(), 2); + + bar.setSearchPattern("a "); + + QCOMPARE(bar.m_hlRanges.size(), numMatches4); + + bar.findAll(); + + QCOMPARE(bar.m_hlRanges.size(), 0); +} + +void SearchBarTest::testReplaceAll() +{ + KateDocument doc(false, false, false); + KateView view(&doc, 0); + KateViewConfig config(&view); + + doc.setText("a a a"); + KateSearchBar bar(true, &view, &config); + + bar.setSearchPattern("a"); + bar.setReplacementPattern(""); + bar.replaceAll(); + + QCOMPARE(bar.m_hlRanges.size(), 3); + QCOMPARE(bar.m_hlRanges.at(0)->toRange(), Range(0, 0, 0, 0)); + QCOMPARE(bar.m_hlRanges.at(1)->toRange(), Range(0, 1, 0, 1)); + QCOMPARE(bar.m_hlRanges.at(2)->toRange(), Range(0, 2, 0, 2)); + + bar.setSearchPattern(" "); + bar.setReplacementPattern("b"); + bar.replaceAll(); + + QCOMPARE(bar.m_hlRanges.size(), 2); + QCOMPARE(bar.m_hlRanges.at(0)->toRange(), Range(0, 0, 0, 1)); + QCOMPARE(bar.m_hlRanges.at(1)->toRange(), Range(0, 1, 0, 2)); +} + +void SearchBarTest::testFindSelectionForward_data() +{ + QTest::addColumn("text"); + QTest::addColumn("selectionOnly"); + QTest::addColumn("selectionRange"); + QTest::addColumn("match"); + + testNewRow() << "a a a" << false << Range(0, 0, 0, 1) << Range(0, 0, 0, 2); + testNewRow() << "a a a" << true << Range(0, 0, 0, 1) << Range(0, 0, 0, 1); + + testNewRow() << "a a a" << false << Range(0, 0, 0, 2) << Range(0, 2, 0, 4); + testNewRow() << "a a a" << true << Range(0, 0, 0, 2) << Range(0, 0, 0, 2); + + testNewRow() << "a a a" << false << Range(0, 0, 0, 3) << Range(0, 0, 0, 2); + testNewRow() << "a a a" << true << Range(0, 0, 0, 3) << Range(0, 0, 0, 2); + + testNewRow() << "a a a" << false << Range(0, 2, 0, 4) << Range(0, 0, 0, 2); + testNewRow() << "a a a" << true << Range(0, 2, 0, 4) << Range(0, 2, 0, 4); + + testNewRow() << "a a a" << false << Range(0, 3, 0, 4) << Range(0, 0, 0, 2); + testNewRow() << "a a a" << true << Range(0, 3, 0, 4) << Range(0, 3, 0, 4); +} + +void SearchBarTest::testFindSelectionForward() +{ + QFETCH(QString, text); + QFETCH(bool, selectionOnly); + QFETCH(Range, selectionRange); + QFETCH(Range, match); + + KateDocument doc(false, false, false); + KateView view(&doc, 0); + KateViewConfig config(&view); + + doc.setText(text); + + view.setSelection(Range(0, 0, 0, 2)); + + KateSearchBar bar(true, &view, &config); + QVERIFY(bar.searchPattern() == QString("a ")); + + view.setSelection(selectionRange); + QCOMPARE(view.selectionRange(), selectionRange); + bar.setSelectionOnly(selectionOnly); + + bar.findNext(); + + QCOMPARE(view.selectionRange(), match); +} + +void SearchBarTest::testRemoveWithSelectionForward_data() +{ + QTest::addColumn("selectionRange"); + QTest::addColumn("match"); + + testNewRow() << Range(0, 0, 0, 1) << Range(0, 0, 0, 2); + testNewRow() << Range(0, 0, 0, 2) << Range(0, 0, 0, 2); + testNewRow() << Range(0, 0, 0, 3) << Range(0, 0, 0, 2); + testNewRow() << Range(0, 2, 0, 4) << Range(0, 0, 0, 2); + testNewRow() << Range(0, 3, 0, 4) << Range(0, 0, 0, 2); +} + +void SearchBarTest::testRemoveWithSelectionForward() +{ + QFETCH(Range, selectionRange); + QFETCH(Range, match); + + KateDocument doc(false, false, false); + KateView view(&doc, 0); + KateViewConfig config(&view); + + doc.setText("a a a"); + view.setSelection(selectionRange); + + KateSearchBar bar(true, &view, &config); + bar.setSearchPattern("a "); + bar.setSelectionOnly(false); + + bar.replaceNext(); + + QCOMPARE(view.selectionRange(), match); +} + +void SearchBarTest::testRemoveInSelectionForward_data() +{ + QTest::addColumn("selectionRange"); + QTest::addColumn("match"); + + testNewRow() << Range(0, 0, 0, 1) << Range(0, 0, 0, 1); + testNewRow() << Range(0, 0, 0, 2) << Range(0, 0, 0, 0); + testNewRow() << Range(0, 0, 0, 3) << Range(0, 0, 0, 2); + testNewRow() << Range(0, 0, 0, 4) << Range(0, 0, 0, 2); + testNewRow() << Range(0, 2, 0, 4) << Range(0, 2, 0, 2); + testNewRow() << Range(0, 3, 0, 4) << Range(0, 3, 0, 4); +} + +void SearchBarTest::testRemoveInSelectionForward() +{ + QFETCH(Range, selectionRange); + QFETCH(Range, match); + + KateDocument doc(false, false, false); + KateView view(&doc, 0); + KateViewConfig config(&view); + + doc.setText("a a a"); + view.setSelection(selectionRange); + + KateSearchBar bar(true, &view, &config); + bar.setSearchPattern("a "); + bar.setSelectionOnly(true); + + QVERIFY(bar.replacementPattern().isEmpty()); + + bar.replaceNext(); + + QCOMPARE(view.selectionRange(), match); +} + +void SearchBarTest::testReplaceWithDoubleSelecion_data() +{ + QTest::addColumn("text"); + QTest::addColumn("selectionRange"); + QTest::addColumn("result"); + QTest::addColumn("match"); + +// testNewRow() << "a" << Range(0, 0, 0, 1) << "aa" << Range(?, ?, ?, ?); + testNewRow() << "aa" << Range(0, 1, 0, 2) << "aaa" << Range(0, 0, 0, 1); + testNewRow() << "aa" << Range(0, 0, 0, 1) << "aaa" << Range(0, 2, 0, 3); + +// testNewRow() << "ab" << Range(0, 0, 0, 1) << "aab" << Range(?, ?, ?, ?); + testNewRow() << "aab" << Range(0, 0, 0, 1) << "aaab" << Range(0, 2, 0, 3); + testNewRow() << "aba" << Range(0, 0, 0, 1) << "aaba" << Range(0, 3, 0, 4); + +// testNewRow() << "ab" << Range(0, 0, 0, 2) << "abab" << Range(?, ?, ?, ?); + testNewRow() << "abab" << Range(0, 0, 0, 2) << "ababab" << Range(0, 4, 0, 6); + testNewRow() << "abab" << Range(0, 2, 0, 4) << "ababab" << Range(0, 0, 0, 2); +} + +void SearchBarTest::testReplaceWithDoubleSelecion() +{ + QFETCH(QString, text); + QFETCH(Range, selectionRange); + QFETCH(QString, result); + QFETCH(Range, match); + + KateDocument doc(false, false, false); + KateView view(&doc, 0); + KateViewConfig config(&view); + + doc.setText(text); + view.setSelection(selectionRange); + + KateSearchBar bar(true, &view, &config); + + bar.setSelectionOnly(false); + bar.setReplacementPattern(bar.searchPattern() + bar.searchPattern()); + bar.replaceNext(); + + QCOMPARE(doc.text(), result); + QCOMPARE(view.selectionRange(), match); +} + +void SearchBarTest::testReplaceDollar() +{ + KateDocument doc(false, false, false); + KateView view(&doc, 0); + KateViewConfig config(&view); + + doc.setText("aaa\nbbb\nccc\n\n\naaa\nbbb\nccc\nddd\n"); + + KateSearchBar bar(true, &view, &config); + + bar.setSearchPattern("$"); + bar.setSearchMode(KateSearchBar::MODE_REGEX); + bar.setReplacementPattern("D"); + + bar.replaceAll(); + + QCOMPARE(doc.text(), QString("aaaD\nbbbD\ncccD\nD\nD\naaaD\nbbbD\ncccD\ndddD\n")); +} + +void SearchBarTest::testSearchHistoryIncremental() +{ + KateDocument doc(false, false, false); + KateView view(&doc, 0); + KateViewConfig *const config = view.config(); + + doc.setText("foo bar"); + + QCOMPARE(config->patternHistoryModel()->stringList(), QStringList()); + + KateSearchBar bar(false, &view, config); + + bar.setSearchPattern("foo"); + bar.findNext(); + + QCOMPARE(bar.m_incUi->pattern->findText("foo"), 0); + + bar.setSearchPattern("bar"); + bar.findNext(); + + QCOMPARE(bar.m_incUi->pattern->findText("bar"), 0); + QCOMPARE(bar.m_incUi->pattern->findText("foo"), 1); + + KateDocument doc2(false, false, false); + KateView view2(&doc2, 0); + KateViewConfig *const config2 = view2.config(); + KateSearchBar bar2(false, &view2, config2); + + QCOMPARE(bar2.m_incUi->pattern->findText("bar"), 0); + QCOMPARE(bar2.m_incUi->pattern->findText("foo"), 1); + + //testcase for https://bugs.kde.org/show_bug.cgi?id=248305 + bar2.m_incUi->pattern->setCurrentIndex(1); + QCOMPARE(bar2.searchPattern(), QLatin1String("foo")); + bar2.findNext(); + QCOMPARE(bar2.searchPattern(), QLatin1String("foo")); +} + +void SearchBarTest::testSearchHistoryPower() +{ + KateDocument doc(false, false, false); + KateView view(&doc, 0); + KateViewConfig *const config = view.config(); + + doc.setText("foo bar"); + + KateSearchBar bar(true, &view, config); + + QCOMPARE(bar.m_powerUi->pattern->count(), 0); + + bar.setSearchPattern("foo"); + bar.findNext(); + + QCOMPARE(bar.m_powerUi->pattern->findText("foo"), 0); + + bar.findNext(); + + QCOMPARE(bar.m_powerUi->pattern->findText("foo"), 0); + QCOMPARE(bar.m_powerUi->pattern->count(), 1); + + bar.setSearchPattern("bar"); + bar.findNext(); + + QCOMPARE(bar.m_powerUi->pattern->findText("bar"), 0); + QCOMPARE(bar.m_powerUi->pattern->findText("foo"), 1); + QCOMPARE(bar.m_powerUi->pattern->count(), 2); + + KateDocument doc2(false, false, false); + KateView view2(&doc2, 0); + KateViewConfig *const config2 = view2.config(); + KateSearchBar bar2(true, &view2, config2); + + QCOMPARE(bar2.m_powerUi->pattern->findText("bar"), 0); + QCOMPARE(bar2.m_powerUi->pattern->findText("foo"), 1); +} + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/share/tests/searchbar_test.h b/share/tests/searchbar_test.h new file mode 100644 index 0000000..78ab26f --- /dev/null +++ b/share/tests/searchbar_test.h @@ -0,0 +1,72 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Bernhard Beschow + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_SEARCHBAR_TEST_H +#define KATE_SEARCHBAR_TEST_H + +#include + +class SearchBarTest : public QObject +{ + Q_OBJECT + +public: + SearchBarTest(); + ~SearchBarTest(); + +private Q_SLOTS: + void testFindNextIncremental(); + + void testSetMatchCaseIncremental(); + + void testSetMatchCasePower(); + + void testSetSelectionOnlyPower(); + + void testSetSearchPattern_data(); + void testSetSearchPattern(); + + void testSetSelectionOnly(); + + void testFindAll_data(); + void testFindAll(); + + void testReplaceAll(); + + void testFindSelectionForward_data(); + void testFindSelectionForward(); + + void testRemoveWithSelectionForward_data(); + void testRemoveWithSelectionForward(); + + void testRemoveInSelectionForward_data(); + void testRemoveInSelectionForward(); + + void testReplaceWithDoubleSelecion_data(); + void testReplaceWithDoubleSelecion(); + + void testReplaceDollar(); + + void testSearchHistoryIncremental(); + void testSearchHistoryPower(); +}; + +#endif + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/share/tests/templatehandler_test.cpp b/share/tests/templatehandler_test.cpp new file mode 100644 index 0000000..da925c8 --- /dev/null +++ b/share/tests/templatehandler_test.cpp @@ -0,0 +1,94 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Bernhard Beschow + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "templatehandler_test.h" +#include "moc_templatehandler_test.cpp" + +#include + +#include +#include + +QTEST_KDEMAIN(TemplateHandlerTest, GUI) + +using namespace KTextEditor; + + +void TemplateHandlerTest::testUndo() +{ + const QString snippet = "for (${type} ${index} = ; ${index} < ; ++${index})\n" + "{\n" + "\t${index}\n" + "}"; + QMap initialValues; + initialValues.insert("type", "int"); + initialValues.insert("index", "i"); + + KateDocument doc(false, false, false, 0, this); + KateView view(&doc, 0); + + doc.insertTemplateTextImplementation(Cursor(0, 0), snippet, initialValues, 0, &view); + + const QString result = "for (int i = ; i < ; ++i)\n" + "{\n" + "\ti\n" + "}"; + QCOMPARE(doc.text(), result); + + doc.replaceText(Range(0, 9, 0, 10), "j"); + + const QString result2 = "for (int j = ; j < ; ++j)\n" + "{\n" + "\tj\n" + "}"; + QCOMPARE(doc.text(), result2); + + doc.undo(); + + QCOMPARE(doc.text(), result); + + doc.redo(); + + QCOMPARE(doc.text(), result2); + + doc.insertText(Cursor(0, 10), "j"); + doc.insertText(Cursor(0, 11), "j"); + + const QString result3 = "for (int jjj = ; jjj < ; ++jjj)\n" + "{\n" + "\tjjj\n" + "}"; + QCOMPARE(doc.text(), result3); + + doc.undo(); + doc.undo(); + + QCOMPARE(doc.text(), result2); + + doc.redo(); + doc.redo(); + + QCOMPARE(doc.text(), result3); + + doc.undo(); + doc.undo(); + doc.undo(); + + QCOMPARE(doc.text(), result); +} diff --git a/share/tests/templatehandler_test.h b/share/tests/templatehandler_test.h new file mode 100644 index 0000000..b414854 --- /dev/null +++ b/share/tests/templatehandler_test.h @@ -0,0 +1,33 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Bernhard Beschow + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_UNDOMANAGER_TEST_H +#define KATE_UNDOMANAGER_TEST_H + +#include + +class TemplateHandlerTest : public QObject +{ + Q_OBJECT + + private Q_SLOTS: + void testUndo(); +}; + +#endif diff --git a/share/tests/test.uc b/share/tests/test.uc new file mode 100644 index 0000000..be53bcc --- /dev/null +++ b/share/tests/test.uc @@ -0,0 +1,266 @@ +//============================================================================= +// Shield Gun +//============================================================================= +class ShieldGun extends Weapon + config(user); + +#EXEC OBJ LOAD FILE=InterfaceContent.utx + +var Sound ShieldHitSound; +var String ShieldHitForce; + +replication +{ + reliable if (Role == ROLE_Authority) + ClientTakeHit; +} + +simulated function DoAutoSwitch() +{ +} + +simulated event RenderOverlays( Canvas Canvas ) +{ + local int m; + + if ((Hand < -1.0) || (Hand > 1.0)) + { + for (m = 0; m < NUM_FIRE_MODES; m++) + { + if (FireMode[m] != None) + { + FireMode[m].DrawMuzzleFlash(Canvas); + } + } + } + Super.RenderOverlays(Canvas); +} + +// AI Interface +function GiveTo(Pawn Other, optional Pickup Pickup) +{ + Super.GiveTo(Other, Pickup); + + if ( Bot(Other.Controller) != None ) + Bot(Other.Controller).bHasImpactHammer = true; +} + +function bool CanAttack(Actor Other) +{ + return true; +} + +simulated function Timer() +{ + local Bot B; + + if (ClientState == WS_BringUp) + { + // check if owner is bot waiting to do impact jump + B = Bot(Instigator.Controller); + if ( (B != None) && B.bPreparingMove && (B.ImpactTarget != None) ) + { + B.ImpactJump(); + B = None; + } + } + Super.Timer(); + if ( (B != None) && (B.Enemy != None) ) + BotFire(false); +} + +function FireHack(byte Mode) +{ + if ( Mode == 0 ) + { + FireMode[0].PlayFiring(); + FireMode[0].FlashMuzzleFlash(); + FireMode[0].StartMuzzleSmoke(); + IncrementFlashCount(0); + } +} + +/* BestMode() +choose between regular or alt-fire +*/ +function byte BestMode() +{ + local float EnemyDist; + local bot B; + + B = Bot(Instigator.Controller); + if ( (B == None) || (B.Enemy == None) ) + return 1; + + EnemyDist = VSize(B.Enemy.Location - Instigator.Location); + if ( EnemyDist > 2 * Instigator.GroundSpeed ) + return 1; + if ( (B.MoveTarget != B.Enemy) && ((EnemyDist > 0.5 * Instigator.GroundSpeed) + || (((B.Enemy.Location - Instigator.Location) Dot vector(Instigator.Rotation)) <= 0)) ) + return 1; + return 0; +} + +// super desireable for bot waiting to impact jump +function float GetAIRating() +{ + local Bot B; + local float EnemyDist; + + B = Bot(Instigator.Controller); + if ( B == None ) + return AIRating; + + if ( B.bPreparingMove && (B.ImpactTarget != None) ) + return 9; + + if ( B.PlayerReplicationInfo.HasFlag != None ) + { + if ( Instigator.Health < 50 ) + return AIRating + 0.35; + return AIRating + 0.25; + } + + if ( B.Enemy == None ) + return AIRating; + + EnemyDist = VSize(B.Enemy.Location - Instigator.Location); + if ( B.Stopped() && (EnemyDist > 100) ) + return 0.1; + + if ( (EnemyDist < 750) && (B.Skill <= 2) && !B.Enemy.IsA('Bot') && (ShieldGun(B.Enemy.Weapon) != None) ) + return FClamp(300/(EnemyDist + 1), 0.6, 0.75); + + if ( EnemyDist > 400 ) + return 0.1; + if ( (Instigator.Weapon != self) && (EnemyDist < 120) ) + return 0.25; + + return ( FMin(0.6, 90/(EnemyDist + 1)) ); +} + +// End AI interface + +function AdjustPlayerDamage( out int Damage, Pawn InstigatedBy, Vector HitLocation, + out Vector Momentum, class DamageType) +{ + local int Drain; + local vector Reflect; + local vector HitNormal; + local float DamageMax; + + DamageMax = 100.0; + if ( DamageType == class'Fell' ) + DamageMax = 20.0; + else if( !DamageType.default.bArmorStops || (DamageType == class'DamTypeShieldImpact' && InstigatedBy == Instigator) ) + return; + + if ( CheckReflect(HitLocation, HitNormal, 0) ) + { + Drain = Min( Ammo[1].AmmoAmount*2, Damage ); + Drain = Min(Drain,DamageMax); + Reflect = MirrorVectorByNormal( Normal(Location - HitLocation), Vector(Instigator.Rotation) ); + Damage -= Drain; + Momentum *= 1.25; + Ammo[1].UseAmmo(Drain/2); + DoReflectEffect(Drain/2); + } +} + +function DoReflectEffect(int Drain) +{ + PlaySound(ShieldHitSound, SLOT_None); + ShieldAltFire(FireMode[1]).TakeHit(Drain); + ClientTakeHit(Drain); +} + +simulated function ClientTakeHit(int Drain) +{ + ClientPlayForceFeedback(ShieldHitForce); + ShieldAltFire(FireMode[1]).TakeHit(Drain); +} + +function bool CheckReflect( Vector HitLocation, out Vector RefNormal, int AmmoDrain ) +{ + local Vector HitDir; + local Vector FaceDir; + + if (!FireMode[1].bIsFiring || Ammo[0].AmmoAmount == 0) return false; + + FaceDir = Vector(Instigator.Controller.Rotation); + HitDir = Normal(Instigator.Location - HitLocation + Vect(0,0,8)); + //Log(self@"HitDir"@(FaceDir dot HitDir)); + + RefNormal = FaceDir; + + if ( FaceDir dot HitDir < -0.37 ) // 68 degree protection arc + { + if (AmmoDrain > 0) + Ammo[0].UseAmmo(AmmoDrain); + return true; + } + return false; +} + +function AnimEnd(int channel) +{ + if (FireMode[0].bIsFiring) + { + LoopAnim('Charged'); + } + else if (!FireMode[1].bIsFiring) + { + Super.AnimEnd(channel); + } +} + +function float SuggestAttackStyle() +{ + return 0.8; +} + +function float SuggestDefenseStyle() +{ + return -0.8; +} + +simulated function float ChargeBar() +{ + return FMin(1,FireMode[0].HoldTime/ShieldFire(FireMode[0]).FullyChargedTime); +} + +defaultproperties +{ + ItemName="Shield Gun" + IconMaterial=Material'InterfaceContent.Hud.SkinA' + IconCoords=(X1=200,Y1=281,X2=321,Y2=371) + + bShowChargingBar=true + bCanThrow=false + FireModeClass(0)=ShieldFire + FireModeClass(1)=ShieldAltFire + InventoryGroup=1 + Mesh=mesh'Weapons.ShieldGun_1st' + BobDamping=2.2 + PickupClass=class'ShieldGunPickup' + EffectOffset=(X=15.0,Y=6.7,Z=1.2) + bMeleeWeapon=true + ShieldHitSound=Sound'WeaponSounds.ShieldGun.ShieldReflection' + DrawScale=0.4 + PutDownAnim=PutDown + DisplayFOV=60 + PlayerViewOffset=(X=2,Y=-0.7,Z=-2.7) + PlayerViewPivot=(Pitch=500,Roll=0,Yaw=500) + + UV2Texture=Material'XGameShaders.WeaponEnvShader' + + AttachmentClass=class'ShieldAttachment' + SelectSound=Sound'WeaponSounds.ShieldGun_change' + SelectForce="ShieldGun_change" + ShieldHitForce="ShieldReflection" + + AIRating=0.35 + CurrentRating=0.35 + + DefaultPriority=2 +} diff --git a/share/tests/testutils.cpp b/share/tests/testutils.cpp new file mode 100644 index 0000000..5c80f05 --- /dev/null +++ b/share/tests/testutils.cpp @@ -0,0 +1,432 @@ +/** + * This file is part of the KDE project + * + * Copyright (C) 2001,2003 Peter Kelly (pmk@post.com) + * Copyright (C) 2003,2004 Stephan Kulow (coolo@kde.org) + * Copyright (C) 2004 Dirk Mueller ( mueller@kde.org ) + * Copyright 2006, 2007 Leo Savernik (l.savernik@aon.at) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +//BEGIN Includes +#include "testutils.h" + +#include "kateview.h" +#include "katedocument.h" +#include "katedocumenthelpers.h" +#include "kateconfig.h" +#include "katecmd.h" +#include "kateglobal.h" +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +//END Includes + +//BEGIN TestScriptEnv + +//BEGIN conversion functions for Cursors and Ranges +/** Converstion function from KTextEditor::Cursor to QtScript cursor */ +static QScriptValue cursorToScriptValue(QScriptEngine *engine, const KTextEditor::Cursor &cursor) +{ + QString code = QString("new Cursor(%1, %2);").arg(cursor.line()) + .arg(cursor.column()); + return engine->evaluate(code); +} + +/** Converstion function from QtScript cursor to KTextEditor::Cursor */ +static void cursorFromScriptValue(const QScriptValue &obj, KTextEditor::Cursor &cursor) +{ + cursor.setPosition(obj.property("line").toInt32(), + obj.property("column").toInt32()); +} + +/** Converstion function from QtScript range to KTextEditor::Range */ +static QScriptValue rangeToScriptValue(QScriptEngine *engine, const KTextEditor::Range &range) +{ + QString code = QString("new Range(%1, %2, %3, %4);").arg(range.start().line()) + .arg(range.start().column()) + .arg(range.end().line()) + .arg(range.end().column()); + return engine->evaluate(code); +} + +/** Converstion function from QtScript range to KTextEditor::Range */ +static void rangeFromScriptValue(const QScriptValue &obj, KTextEditor::Range &range) +{ + range.start().setPosition(obj.property("start").property("line").toInt32(), + obj.property("start").property("column").toInt32()); + range.end().setPosition(obj.property("end").property("line").toInt32(), + obj.property("end").property("column").toInt32()); +} +//END + +TestScriptEnv::TestScriptEnv(KateDocument *part, bool &cflag) + : m_engine(0), m_viewObj(0), m_docObj(0), m_output(0) +{ + m_engine = new QScriptEngine(this); + + qScriptRegisterMetaType (m_engine, cursorToScriptValue, cursorFromScriptValue); + qScriptRegisterMetaType (m_engine, rangeToScriptValue, rangeFromScriptValue); + + initApi(); + + KateView *view = qobject_cast(part->widget()); + + m_viewObj = new KateViewObject(view); + QScriptValue sv = m_engine->newQObject(m_viewObj); + + m_engine->globalObject().setProperty("view", sv); + m_engine->globalObject().setProperty("v", sv); + + m_docObj = new KateDocumentObject(view->doc()); + QScriptValue sd = m_engine->newQObject(m_docObj); + + m_engine->globalObject().setProperty("document", sd); + m_engine->globalObject().setProperty("d", sd); + + m_output = new OutputObject(view, cflag); + QScriptValue so = m_engine->newQObject(m_output); + + m_engine->globalObject().setProperty("output", so); + m_engine->globalObject().setProperty("out", so); + m_engine->globalObject().setProperty("o", so); +} + +TestScriptEnv::~TestScriptEnv() +{ + // delete explicitly, as the parent is the KTE::Document kpart, which is + // reused for all tests. Hence, we explicitly have to delete the bindings. + delete m_output; m_output = 0; + delete m_docObj; m_docObj = 0; + delete m_viewObj; m_viewObj = 0; + + // delete this too, although this should also be automagically be freed + delete m_engine; m_engine = 0; + +// kDebug() << "deleted"; +} + +void TestScriptEnv::initApi() +{ + // cache file names + static QStringList apiFileBaseNames; + static QHash apiBaseName2FileName; + static QHash apiBaseName2Content; + + // read katepart javascript api + apiFileBaseNames.clear (); + apiBaseName2FileName.clear (); + apiBaseName2Content.clear (); + + // get all api files + const QStringList list = KGlobal::dirs()->findAllResources("data","katepart/api/*.js", KStandardDirs::NoDuplicates); + + for ( QStringList::ConstIterator it = list.begin(); it != list.end(); ++it ) + { + // get abs filename.... + QFileInfo fi(*it); + const QString absPath = fi.absoluteFilePath(); + const QString baseName = fi.baseName (); + + // remember filenames + apiFileBaseNames.append (baseName); + apiBaseName2FileName[baseName] = absPath; + + // read the file + QFile file(absPath); + QString content; + if (!file.open(QIODevice::ReadOnly)) { + kFatal() << i18n("Unable to find '%1'", absPath); + return; + } else { + QTextStream stream(&file); + stream.setCodec("UTF-8"); + content = stream.readAll(); + file.close(); + } + apiBaseName2Content[baseName] = content; + } + + // sort... + apiFileBaseNames.sort (); + + // register all script apis found + for ( QStringList::ConstIterator it = apiFileBaseNames.constBegin(); it != apiFileBaseNames.constEnd(); ++it ) + { + // try to load into engine, bail out one error, use fullpath for error messages + QScriptValue apiObject = m_engine->evaluate(apiBaseName2Content[*it], apiBaseName2FileName[*it]); + + if(m_engine->hasUncaughtException()) { + kFatal() << "Error loading script" << (*it); + return; + } + } + + // success ;) +} + +//END TestScriptEnv + +//BEGIN KateViewObject + +KateViewObject::KateViewObject(KateView *view) + : KateScriptView() +{ + setView(view); +} + +KateViewObject::~KateViewObject() +{ +// kDebug() << "deleted"; +} + +// Implements a function that calls an edit function repeatedly as specified by +// its first parameter (once if not specified). +#define REP_CALL(func) \ +void KateViewObject::func(int cnt) { \ + while (cnt--) { view()->func(); } \ +} +REP_CALL(keyReturn) +REP_CALL(backspace) +REP_CALL(deleteWordLeft) +REP_CALL(keyDelete) +REP_CALL(deleteWordRight) +REP_CALL(transpose) +REP_CALL(cursorLeft) +REP_CALL(shiftCursorLeft) +REP_CALL(cursorRight) +REP_CALL(shiftCursorRight) +REP_CALL(wordLeft) +REP_CALL(shiftWordLeft) +REP_CALL(wordRight) +REP_CALL(shiftWordRight) +REP_CALL(home) +REP_CALL(shiftHome) +REP_CALL(end) +REP_CALL(shiftEnd) +REP_CALL(up) +REP_CALL(shiftUp) +REP_CALL(down) +REP_CALL(shiftDown) +REP_CALL(scrollUp) +REP_CALL(scrollDown) +REP_CALL(topOfView) +REP_CALL(shiftTopOfView) +REP_CALL(bottomOfView) +REP_CALL(shiftBottomOfView) +REP_CALL(pageUp) +REP_CALL(shiftPageUp) +REP_CALL(pageDown) +REP_CALL(shiftPageDown) +REP_CALL(top) +REP_CALL(shiftTop) +REP_CALL(bottom) +REP_CALL(shiftBottom) +REP_CALL(toMatchingBracket) +REP_CALL(shiftToMatchingBracket) +#undef REP_CALL + +bool KateViewObject::type(const QString& str) { + return view()->doc()->typeChars(view(), str); +} + +#define ALIAS(alias, func) \ +void KateViewObject::alias(int cnt) { \ + func(cnt); \ +} +ALIAS(enter, keyReturn) +ALIAS(cursorPrev, cursorLeft) +ALIAS(left, cursorLeft) +ALIAS(prev, cursorLeft) +ALIAS(shiftCursorPrev, shiftCursorLeft) +ALIAS(shiftLeft, shiftCursorLeft) +ALIAS(shiftPrev, shiftCursorLeft) +ALIAS(cursorNext, cursorRight) +ALIAS(right, cursorRight) +ALIAS(next, cursorRight) +ALIAS(shiftCursorNext, shiftCursorRight) +ALIAS(shiftRight, shiftCursorRight) +ALIAS(shiftNext, shiftCursorRight) +ALIAS(wordPrev, wordLeft) +ALIAS(shiftWordPrev, shiftWordLeft) +ALIAS(wordNext, wordRight) +ALIAS(shiftWordNext, shiftWordRight) +#undef ALIAS + +//END KateViewObject + +//BEGIN KateDocumentObject + +KateDocumentObject::KateDocumentObject(KateDocument *doc) + : KateScriptDocument() +{ + setDocument(doc); +} + +KateDocumentObject::~KateDocumentObject() +{ +// kDebug() << "deleted"; +} +//END KateDocumentObject + +//BEGIN OutputObject + +OutputObject::OutputObject(KateView *v, bool &cflag) + : view(v), cflag(cflag) +{ +} + +OutputObject::~OutputObject() +{ +// kDebug() << "deleted"; +} + +void OutputObject::output(bool cp, bool ln) +{ + QString str; + for (int i = 0; i < context()->argumentCount(); ++i) { + QScriptValue arg = context()->argument(i); + str += arg.toString(); + } + + if (cp) { + KTextEditor::Cursor c = view->cursorPosition(); + str += '(' + QString::number(c.line()) + ',' + QString::number(c.column()) + ')'; + } + + if (ln) { + str += '\n'; + } + + view->insertText(str); + + cflag = true; +} + +void OutputObject::write() +{ + output(false, false); +} + +void OutputObject::writeln() +{ + output(false, true); +} + +void OutputObject::writeLn() +{ + output(false, true); +} + +void OutputObject::print() +{ + output(false, false); +} + +void OutputObject::println() +{ + output(false, true); +} + +void OutputObject::printLn() +{ + output(false, true); +} + +void OutputObject::writeCursorPosition() +{ + output(true, false); +} + +void OutputObject::writeCursorPositionln() +{ + output(true, true); +} + +void OutputObject::cursorPosition() +{ + output(true, false); +} + +void OutputObject::cursorPositionln() +{ + output(true, true); +} + +void OutputObject::cursorPositionLn() +{ + output(true, true); +} + +void OutputObject::pos() +{ + output(true, false); +} + +void OutputObject::posln() +{ + output(true, true); +} + +void OutputObject::posLn() +{ + output(true, true); +} + +//END OutputObject diff --git a/share/tests/testutils.h b/share/tests/testutils.h new file mode 100644 index 0000000..ca2bc04 --- /dev/null +++ b/share/tests/testutils.h @@ -0,0 +1,194 @@ +/** + * This file is part of the KDE project + * + * Copyright (C) 2001,2003 Peter Kelly (pmk@post.com) + * Copyright 2006, 2007 Leo Savernik (l.savernik@aon.at) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; see the file COPYING.LIB. If not, write to + * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ +#ifndef TESTUTILS_H +#define TESTUTILS_H + +#include "katescriptview.h" +#include "katescriptdocument.h" + +#include + +class KateView; +class RegressionTest; +class KCmdLineArgs; +class OutputObject; +class KateViewObject; +class KateDocumentObject; + +/** + * @internal + * The backbone of Kate's automatic regression tests. + */ +class TestScriptEnv : public QObject +{ + public: + explicit TestScriptEnv(KateDocument *part, bool &cflag); + virtual ~TestScriptEnv(); + + QScriptEngine *engine() const { return m_engine; } + + /** returns the output object */ + OutputObject *output() const { return m_output; } + + private: + void initApi(); + QScriptEngine *m_engine; + KateViewObject *m_viewObj; + KateDocumentObject *m_docObj; + + OutputObject *m_output; +}; + +/** + * @internal + */ +class KateViewObject : public KateScriptView +{ + Q_OBJECT + + public: + + explicit KateViewObject(KateView *view); + virtual ~KateViewObject(); + + // Edit functions + Q_INVOKABLE void keyReturn(int cnt = 1); + Q_INVOKABLE void backspace(int cnt = 1); + Q_INVOKABLE void deleteWordLeft(int cnt = 1); + Q_INVOKABLE void keyDelete(int cnt = 1); + Q_INVOKABLE void deleteWordRight(int cnt = 1); + Q_INVOKABLE void transpose(int cnt = 1); + Q_INVOKABLE void cursorLeft(int cnt = 1); + Q_INVOKABLE void shiftCursorLeft(int cnt = 1); + Q_INVOKABLE void cursorRight(int cnt = 1); + Q_INVOKABLE void shiftCursorRight(int cnt = 1); + Q_INVOKABLE void wordLeft(int cnt = 1); + Q_INVOKABLE void shiftWordLeft(int cnt = 1); + Q_INVOKABLE void wordRight(int cnt = 1); + Q_INVOKABLE void shiftWordRight(int cnt = 1); + Q_INVOKABLE void home(int cnt = 1); + Q_INVOKABLE void shiftHome(int cnt = 1); + Q_INVOKABLE void end(int cnt = 1); + Q_INVOKABLE void shiftEnd(int cnt = 1); + Q_INVOKABLE void up(int cnt = 1); + Q_INVOKABLE void shiftUp(int cnt = 1); + Q_INVOKABLE void down(int cnt = 1); + Q_INVOKABLE void shiftDown(int cnt = 1); + Q_INVOKABLE void scrollUp(int cnt = 1); + Q_INVOKABLE void scrollDown(int cnt = 1); + Q_INVOKABLE void topOfView(int cnt = 1); + Q_INVOKABLE void shiftTopOfView(int cnt = 1); + Q_INVOKABLE void bottomOfView(int cnt = 1); + Q_INVOKABLE void shiftBottomOfView(int cnt = 1); + Q_INVOKABLE void pageUp(int cnt = 1); + Q_INVOKABLE void shiftPageUp(int cnt = 1); + Q_INVOKABLE void pageDown(int cnt = 1); + Q_INVOKABLE void shiftPageDown(int cnt = 1); + Q_INVOKABLE void top(int cnt = 1); + Q_INVOKABLE void shiftTop(int cnt = 1); + Q_INVOKABLE void bottom(int cnt = 1); + Q_INVOKABLE void shiftBottom(int cnt = 1); + Q_INVOKABLE void toMatchingBracket(int cnt = 1); + Q_INVOKABLE void shiftToMatchingBracket(int cnt = 1); + + Q_INVOKABLE bool type(const QString& str); + + // Aliases + Q_INVOKABLE void enter(int cnt = 1); // KeyReturn + Q_INVOKABLE void cursorPrev(int cnt = 1); // CursorLeft + Q_INVOKABLE void left(int cnt = 1); // CursorLeft + Q_INVOKABLE void prev(int cnt = 1); // CursorLeft + Q_INVOKABLE void shiftCursorPrev(int cnt = 1); // ShiftCursorLeft + Q_INVOKABLE void shiftLeft(int cnt = 1); // ShiftCursorLeft + Q_INVOKABLE void shiftPrev(int cnt = 1); // ShiftCursorLeft + Q_INVOKABLE void cursorNext(int cnt = 1); // CursorRight + Q_INVOKABLE void right(int cnt = 1); // CursorRight + Q_INVOKABLE void next(int cnt = 1); // CursorRight + Q_INVOKABLE void shiftCursorNext(int cnt = 1); // ShiftCursorRight + Q_INVOKABLE void shiftRight(int cnt = 1); // ShiftCursorRight + Q_INVOKABLE void shiftNext(int cnt = 1); // ShiftCursorRight + Q_INVOKABLE void wordPrev(int cnt = 1); // WordLeft + Q_INVOKABLE void shiftWordPrev(int cnt = 1); // ShiftWordLeft + Q_INVOKABLE void wordNext(int cnt = 1); // WordRight + Q_INVOKABLE void shiftWordNext(int cnt = 1); // ShiftWordRight + + private: + Q_DISABLE_COPY(KateViewObject) +}; + +/** + * @internal + */ +class KateDocumentObject : public KateScriptDocument +{ + Q_OBJECT + + public: + explicit KateDocumentObject(KateDocument* doc); + virtual ~KateDocumentObject(); + + private: + Q_DISABLE_COPY(KateDocumentObject) +}; + +/** + * Customizing output to result-files. Writing any output into result files + * inhibits outputting the content of the katepart after script execution, + * enabling one to check for coordinates and the like. + * @internal + */ +class OutputObject : public QObject, protected QScriptable +{ + Q_OBJECT + + public: + OutputObject(KateView *v, bool &cflag); + virtual ~OutputObject(); + + void output(bool cp, bool ln); + + Q_INVOKABLE void write(); + Q_INVOKABLE void writeln(); + Q_INVOKABLE void writeLn(); + + Q_INVOKABLE void print(); + Q_INVOKABLE void println(); + Q_INVOKABLE void printLn(); + + Q_INVOKABLE void writeCursorPosition(); + Q_INVOKABLE void writeCursorPositionln(); + + Q_INVOKABLE void cursorPosition(); + Q_INVOKABLE void cursorPositionln(); + Q_INVOKABLE void cursorPositionLn(); + + Q_INVOKABLE void pos(); + Q_INVOKABLE void posln(); + Q_INVOKABLE void posLn(); + + private: + KateView *view; + bool &cflag; +}; + +#endif // TESTUTILS_H diff --git a/share/tests/undomanager_test.cpp b/share/tests/undomanager_test.cpp new file mode 100644 index 0000000..5cbd2ba --- /dev/null +++ b/share/tests/undomanager_test.cpp @@ -0,0 +1,199 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Bernhard Beschow + Copyright (C) 2009 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#include "undomanager_test.h" +#include "moc_undomanager_test.cpp" + +#include + +#include +#include +#include + +QTEST_KDEMAIN(UndoManagerTest, GUI) + +using namespace KTextEditor; + +class UndoManagerTest::TestDocument : public KateDocument +{ +public: + TestDocument() + : KateDocument(false, false, false, 0, 0) + {} +}; + +void UndoManagerTest::testUndoRedoCount() +{ + TestDocument doc; + KateUndoManager *undoManager = doc.undoManager(); + + // no undo/redo items at the beginning + QCOMPARE(undoManager->undoCount(), 0u); + QCOMPARE(undoManager->redoCount(), 0u); + + doc.insertText(Cursor(0, 0), "a"); + + // create one insert-group + QCOMPARE(undoManager->undoCount(), 1u); + QCOMPARE(undoManager->redoCount(), 0u); + + doc.undo(); + + // move insert-group to redo items + QCOMPARE(undoManager->undoCount(), 0u); + QCOMPARE(undoManager->redoCount(), 1u); + + doc.redo(); + + // move insert-group back to undo items + QCOMPARE(undoManager->undoCount(), 1u); + QCOMPARE(undoManager->redoCount(), 0u); + + doc.insertText(Cursor(0, 1), "b"); + + // merge "b" into insert-group + QCOMPARE(undoManager->undoCount(), 1u); + QCOMPARE(undoManager->redoCount(), 0u); + + doc.removeText(Range(0, 1, 0, 2)); + + // create an additional remove-group + QCOMPARE(undoManager->undoCount(), 2u); + QCOMPARE(undoManager->redoCount(), 0u); + + doc.undo(); + + // move remove-group to redo items + QCOMPARE(undoManager->undoCount(), 1u); + QCOMPARE(undoManager->redoCount(), 1u); + + doc.insertText(Cursor(0, 1), "b"); + + // merge "b" into insert-group + // and remove remove-group + QCOMPARE(undoManager->undoCount(), 1u); + QCOMPARE(undoManager->redoCount(), 0u); +} + +void UndoManagerTest::testSafePoint() +{ + TestDocument doc; + KateUndoManager *undoManager = doc.undoManager(); + + doc.insertText(Cursor(0, 0), "a"); + + // create one undo group + QCOMPARE(undoManager->undoCount(), 1u); + QCOMPARE(undoManager->redoCount(), 0u); + + undoManager->undoSafePoint(); + doc.insertText(Cursor(0, 1), "b"); + + // create a second undo group (don't merge) + QCOMPARE(undoManager->undoCount(), 2u); + + doc.undo(); + + // move second undo group to redo items + QCOMPARE(undoManager->undoCount(), 1u); + QCOMPARE(undoManager->redoCount(), 1u); + + doc.insertText(Cursor(0, 1), "b"); + + // create a second undo group again, (don't merge) + QCOMPARE(undoManager->undoCount(), 2u); + QCOMPARE(undoManager->redoCount(), 0u); + + doc.editStart(); + doc.insertText(Cursor(0, 2), "c"); + undoManager->undoSafePoint(); + doc.insertText(Cursor(0, 3), "d"); + doc.editEnd(); + + // merge both edits into second undo group + QCOMPARE(undoManager->undoCount(), 2u); + QCOMPARE(undoManager->redoCount(), 0u); + + doc.insertText(Cursor(0, 4), "e"); + + // create a third undo group (don't merge) + QCOMPARE(undoManager->undoCount(), 3u); + QCOMPARE(undoManager->redoCount(), 0u); +} + +void UndoManagerTest::testCursorPosition() +{ + TestDocument doc; + KateView *view = static_cast(doc.createView(0)); + + doc.setText("aaaa bbbb cccc\n" + "dddd ffff"); + view->setCursorPosition(KTextEditor::Cursor(1, 5)); + + doc.typeChars(view, "eeee"); + + // cursor position: "dddd eeee| ffff" + QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(1, 9)); + + // undo once to remove "eeee", cursor position: "dddd | ffff" + doc.undo(); + QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(1, 5)); + + // redo once to insert "eeee" again. cursor position: "dddd eeee| ffff" + doc.redo(); + QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(1, 9)); + + delete view; +} + +void UndoManagerTest::testSelectionUndo() +{ + TestDocument doc; + KateView *view = static_cast(doc.createView(0)); + + doc.setText("aaaa bbbb cccc\n" + "dddd eeee ffff"); + view->setCursorPosition(KTextEditor::Cursor(1, 9)); + KTextEditor::Range selectionRange(KTextEditor::Cursor(0, 5), + KTextEditor::Cursor(1, 9)); + view->setSelection(selectionRange); + + doc.typeChars(view, "eeee"); + + // cursor position: "aaaa eeee| ffff", no selection anymore + QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(0, 9)); + QCOMPARE(view->selection(), false); + + // undo to remove "eeee" and add selection and text again + doc.undo(); + QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(1, 9)); + QCOMPARE(view->selection(), true); + QCOMPARE(view->selectionRange(), selectionRange); + + // redo to insert "eeee" again and remove selection + // cursor position: "aaaa eeee| ffff", no selection anymore + doc.redo(); + QCOMPARE(view->cursorPosition(), KTextEditor::Cursor(0, 9)); + QCOMPARE(view->selection(), false); + + delete view; +} + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/share/tests/undomanager_test.h b/share/tests/undomanager_test.h new file mode 100644 index 0000000..2e5ea1f --- /dev/null +++ b/share/tests/undomanager_test.h @@ -0,0 +1,42 @@ +/* This file is part of the KDE libraries + Copyright (C) 2010 Bernhard Beschow + Copyright (C) 2009 Dominik Haumann + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef KATE_UNDOMANAGER_TEST_H +#define KATE_UNDOMANAGER_TEST_H + +#include + +class UndoManagerTest : public QObject +{ + Q_OBJECT + + private Q_SLOTS: + void testUndoRedoCount(); + void testSafePoint(); + void testCursorPosition(); + void testSelectionUndo(); + + private: + class TestDocument; +}; + +#endif + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/share/tests/vimode_test.cpp b/share/tests/vimode_test.cpp new file mode 100644 index 0000000..42d711b --- /dev/null +++ b/share/tests/vimode_test.cpp @@ -0,0 +1,680 @@ +/* This file is part of the KDE libraries + + Copyright (C) 2011 Kuzmich Svyatoslav + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + */ + +#include "vimode_test.h" +#include "moc_vimode_test.cpp" + +#include +#include +#include +#include +#include "kateconfig.h" +#include "katebuffer.h" +#include "katevikeyparser.h" +#include "kateviewhelpers.h" + +QTEST_KDEMAIN(ViModeTest, GUI) + +using namespace KTextEditor; + +ViModeTest::ViModeTest() { + kate_document = new KateDocument(false, false, false, 0, NULL); + kate_view = new KateView(kate_document, 0); + vi_input_mode_manager = kate_view->getViInputModeManager(); +} + + +ViModeTest::~ViModeTest() { + delete kate_document; +// delete kate_view; +} + +void ViModeTest::TestPressKey(QString str) { + QKeyEvent *key_event; + QString key; + Qt::KeyboardModifiers keyboard_modifier; + + for (int i = 0; i< str.length(); i++) { + // Looking for keyboard modifiers + if (str[i] == QChar('\\')) { + if (str.mid(i,6) == QString("\\ctrl-")){ + keyboard_modifier = Qt::ControlModifier; + i+=6; + } else if (str.mid(i,4) == QString("\\alt-")) { + keyboard_modifier = Qt::AltModifier; + i+=4; + } else if (str.mid(i,5) == QString("\\meta-")) { + keyboard_modifier = Qt::MetaModifier; + i+=5; + } else if (str.mid(i,2) == QString("\\:")) { + int start_cmd = i+2; + for( i+=2 ; str.at(i) != '\\' ; i++ ) {} + kate_view->cmdLineBar()->execute(str.mid(start_cmd,i-start_cmd)); + } else { + assert(false); //Do not use "\" in tests except for modifiers and command mode. + } + } else { + keyboard_modifier = Qt::NoModifier; + } + + key = str[i]; + + int code; + if (vi_input_mode_manager->getCurrentViMode() == InsertMode){ + code = key[0].unicode() - 'a' + Qt::Key_A; + } else { + code = key[0].unicode() - '0' + Qt::Key_0; + } + + key_event = new QKeyEvent(QEvent::KeyRelease, code, keyboard_modifier, key); + vi_input_mode_manager->handleKeypress(key_event); + } +} + + +/** + * Starts normal mode. + * Makes commad on original_text and compare result with expected test. + * There is a possibility to use keyboard modifiers Ctrl, Alt and Meta. + * For example: + * DoTest("line 1\nline 2\n","ddu\\ctrl-r","line 2\n"); + */ +void ViModeTest::DoTest(QString original_text, + QString command, + QString expected_text) { + qDebug() << "\n\n>>> running command " << command << " on text " << original_text; + + vi_input_mode_manager->viEnterNormalMode(); + vi_input_mode_manager = kate_view->resetViInputModeManager(); + kate_document->setText(original_text); + kate_view->setCursorPosition(Cursor(0,0)); + TestPressKey(command); + + QCOMPARE(kate_document->text(), expected_text); + +} + + + +void ViModeTest::VisualModeTests() { + DoTest("foobar", "vlllx", "ar"); + DoTest("foo\nbar", "Vd", "bar"); + DoTest("1234\n1234\n1234", "l\\ctrl-vljjd", "14\n14\n14"); + + DoTest("12345678", "lv3lyx", "1345678"); + DoTest("12345678", "$hv3hyx", "1235678"); + DoTest("aaa\nbbb", "lvj~x", "aA\nBBb"); + DoTest("123\n456", "jlvkyx", "13\n456"); + DoTest("12\n34","lVjyx", "2\n34"); + DoTest("ab\ncd","jVlkgux", "a\ncd"); + DoTest("ABCD\nABCD\nABCD\nABCD","lj\\ctrl-vjlgux","ABCD\nAcD\nAbcD\nABCD"); + DoTest("abcd\nabcd\nabcd\nabcd","jjjlll\\ctrl-vkkhgUx","abcd\nabD\nabCD\nabCD"); + + // Testing "d" + DoTest("foobarbaz","lvlkkjl2ld","fbaz"); + DoTest("foobar","v$d",""); + DoTest("foo\nbar\nbaz","jVlld","foo\nbaz"); + + // Testing "D" + DoTest("foo\nbar\nbaz","lvjlD","baz"); + DoTest("foo\nbar", "l\\ctrl-vjD","f\nb"); + DoTest("foo\nbar","VjkD","bar"); + + // Testing "gU", "U" + DoTest("foo bar", "vwgU", "FOO Bar"); + DoTest("foo\nbar\nbaz", "VjjU", "FOO\nBAR\nBAZ"); + DoTest("foo\nbar\nbaz", "\\ctrl-vljjU","FOo\nBAr\nBAz"); + + // Testing "gu", "u" + DoTest("TEST", "Vgu", "test"); + DoTest("TeSt", "vlgu","teSt"); + DoTest("FOO\nBAR\nBAZ", "\\ctrl-vljju","foO\nbaR\nbaZ"); + + // Testing "y" + DoTest("foobar","Vypp","foobar\nfoobar\nfoobar"); + DoTest("foo\nbar","lvjlyp", "fooo\nbaro\nbar"); + DoTest("foo\nbar","Vjlllypddxxxdd","foo\nbar"); + DoTest("12\n12", "\\ctrl-vjyp", "112\n112"); + DoTest("1234\n1234\n1234\n1234","lj\\ctrl-vljyp","1234\n122334\n122334\n1234"); + + // Testing "Y" + DoTest("foo\nbar","llvjypx","foo\nbar\nbar"); + DoTest("foo\nbar","VYp","foo\nfoo\nbar"); + + // Testing "m." + DoTest("foo\nbar","vljmavgg`ax","foo\nbr"); + DoTest("1\n2\n3\n4","Vjmajjmb\\:'a,'bd\\","1"); + + // Testing ">" + DoTest("foo\nbar","vj>"," foo\n bar"); + DoTest("foo\nbar\nbaz", "jVj>", "foo\n bar\n baz"); + DoTest("foo", "vl3>"," foo"); + + // Testing "<" + DoTest(" foo","vl<", "foo"); + + // Testing "o" + DoTest("foobar","lv2lo2ld","fooar"); + DoTest("foo\nbar","jvllokld","f"); + DoTest("12\n12","\\ctrl-vjlold","1\n1"); + + // Testing "~" + DoTest("foobar","lv2l~","fOOBar"); + DoTest("FooBar","V~","fOObAR"); + DoTest("foo\nbar","\\ctrl-vjl~","FOo\nBAr"); + + // Testing "r" + DoTest("foobar","Vra","aaaaaa"); + DoTest("foo\nbar","jlvklrx","fox\nxxr"); + DoTest("123\n123","l\\ctrl-vljrx","1xx\n1xx"); + + // Testing "gq" + DoTest("foo\nbar\nbaz","Vgq","foo\nbar\nbaz"); + DoTest("foo\nbar\nbaz","Vjgq","foo bar\nbaz"); + + // Testing "<<"/">>" + kate_document->config()->setReplaceTabsDyn(true); + DoTest("foo\nbar\nbaz","V>>"," foo\nbar\nbaz"); + DoTest("foo\nbar\nbaz","Vj>>"," foo\n bar\nbaz"); + DoTest("foo\nbar\nbaz","V2j>>"," foo\n bar\n baz"); + DoTest("foo\nbar\nbaz","V10>>"," foo\nbar\nbaz"); + DoTest("foo\nbar\nbaz","V2j3>>"," foo\n bar\n baz"); + + DoTest(" foo\nbar\nbaz","V<<","foo\nbar\nbaz"); + DoTest("foo\nbar\nbaz","V>>V<<","foo\nbar\nbaz"); + DoTest(" foo\n bar\n baz","V2j<<"," foo\n bar\n baz"); +} + +void ViModeTest::InsertModeTests() { + + DoTest("bar", "s\\ctrl-c", "ar"); + DoTest("bar", "ls\\ctrl-cx", "r"); + DoTest("foo\nbar", "S\\ctrl-c", "\nbar"); + DoTest("baz bar", "lA\\ctrl-cx", "baz ba"); + DoTest("baz bar", "la\\ctrl-cx", "bz bar"); + DoTest("foo\nbar\nbaz", "C\\ctrl-c", "\nbar\nbaz"); + DoTest("foo bar baz", "c2w\\ctrl-c", " baz"); + DoTest("foo\nbar\nbaz", "jo\\ctrl-c", "foo\nbar\n\nbaz"); + DoTest("foo\nbar\nbaz", "jO\\ctrl-c", "foo\n\nbar\nbaz"); + DoTest("foo\nbar", "O\\ctrl-c", "\nfoo\nbar"); + DoTest("foo\nbar", "o\\ctrl-c", "foo\n\nbar"); + DoTest("foo bar", "wlI\\ctrl-cx", "oo bar"); + DoTest("foo bar", "wli\\ctrl-cx", "foo ar"); + + // Testing "Ctrl-w" + DoTest("foobar", "$i\\ctrl-w", "r"); + DoTest("foobar\n", "A\\ctrl-w", "\n"); + + // Testing "Ctrl-e" + DoTest("foo\nbar", "i\\ctrl-e", "bfoo\nbar"); + DoTest("foo\nbar", "i\\ctrl-e\\ctrl-e\\ctrl-e", "barfoo\nbar"); + DoTest("foo\nb", "i\\ctrl-e\\ctrl-e", "bfoo\nb"); + + // Testing "Ctrl-y" + DoTest("foo\nbar", "ji\\ctrl-y", "foo\nfbar"); + DoTest("foo\nbar", "ji\\ctrl-y\\ctrl-y\\ctrl-y", "foo\nfoobar"); + DoTest("f\nbar", "ji\\ctrl-y\\ctrl-y", "f\nfbar"); + + // Testing "Ctrl-R" + DoTest("barbaz", "\"ay3li\\ctrl-ra", "barbarbaz"); + DoTest("bar\nbaz", "\"byylli\\ctrl-rb", "bar\nbar\nbaz" ); + + // Testing "Ctrl-O" + DoTest("foo bar baz","3li\\ctrl-od2w","foobaz"); + DoTest("foo bar baz","3li\\ctrl-od2w\\ctrl-w","baz"); + DoTest("foo bar baz","i\\ctrl-o3l\\ctrl-w"," bar baz"); + DoTest("foo\nbar\nbaz","li\\ctrl-oj\\ctrl-w\\ctrl-oj\\ctrl-w","foo\nar\naz"); + + // Testing "Ctrl-D" "Ctrl-T" + DoTest("foo", "i\\ctrl-t" , " foo"); + DoTest(" foo", "i\\ctrl-d", "foo"); + DoTest("foo\nbar", "i\\ctrl-t\\ctrl-d","foo\nbar" ); + + // Testing "Ctrl-H" + DoTest("foo", "i\\ctrl-h" , "foo"); + DoTest(" foo", "li\\ctrl-h", "foo"); + DoTest("foo\nbar", "ji\\ctrl-h","foobar" ); + DoTest("1234567890", "A\\ctrl-h\\ctrl-h\\ctrl-h\\ctrl-h\\ctrl-h","12345"); + DoTest("1\n2\n3", "GA\\ctrl-h\\ctrl-h\\ctrl-h\\ctrl-h","1"); + + // Testing "Ctrl-J" + DoTest("foo", "i\\ctrl-j" , "\nfoo"); + DoTest("foo", "lli\\ctrl-j", "fo\no"); + DoTest("foo\nbar", "ji\\ctrl-j","foo\n\nbar"); + DoTest("foobar", "A\\ctrl-j","foobar\n" ); + DoTest("foobar", "li\\ctrl-j\\ctrl-cli\\ctrl-j\\ctrl-cli\\ctrl-j\\ctrl-cli\\ctrl-j\\ctrl-cli\\ctrl-j\\ctrl-c","f\no\no\nb\na\nr"); +} + + + // There are written tests that fail. + // They are disabled in order to be able to check all others working tests. +void ViModeTest::NormalModeFallingTests() +{ + +} + +void ViModeTest::NormalModeMotionsTest() { + + // Test moving around an empty document (nothing should happen) + DoTest("", "jkhl", ""); + DoTest("", "ggG$0", ""); + + //Testing "l" + DoTest("bar", "lx", "br"); + DoTest("bar", "2lx", "ba"); + DoTest("0123456789012345", "13lx", "012345678901245"); + DoTest("bar", "10lx", "ba"); + + // Testing "h" + DoTest("bar", "llhx", "br"); + DoTest("bar", "10l10hx", "ar"); + DoTest("0123456789012345", "13l10hx", "012456789012345"); + DoTest("bar", "ll5hx", "ar"); + + // Testing "j" + DoTest("bar\nbar", "jx", "bar\nar"); + DoTest("bar\nbar", "10jx", "bar\nar"); + DoTest("bar\nbara", "lljx", "bar\nbaa"); + DoTest("0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n0\n1\n2\n3\n4\n5\n", + "13jx", + "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n0\n1\n2\n\n4\n5\n"); + + // Testing "k" + DoTest("bar\nbar", "jx", "bar\nar"); + DoTest("bar\nbar\nbar", "jj100kx", "ar\nbar\nbar"); + DoTest("0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n0\n1\n2\n3\n4\n5\n", + "13j10kx", + "0\n1\n2\n\n4\n5\n6\n7\n8\n9\n0\n1\n2\n3\n4\n5\n"); + + // Testing "w" + DoTest("bar", "wx", "ba"); + DoTest("foo bar", "wx", "foo ar"); + DoTest("foo bar", "lwx","foo ar"); + DoTest("quux(foo, bar, baz);", "wxwxwxwx2wx","quuxfoo ar baz;"); + DoTest("foo\nbar\nbaz", "wxwx","foo\nar\naz"); + DoTest("1 2 3\n4 5 6", "ld3w", "1\n4 5 6"); + DoTest("foo\nbar baz", "gU2w", "FOO\nBAR baz"); + DoTest("FOO\nBAR BAZ", "gu2w", "foo\nbar BAZ"); + + + // Testing "W" + DoTest("bar", "Wx", "ba"); + DoTest("foo bar", "Wx", "foo ar"); + DoTest("foo bar", "2lWx","foo ar"); + DoTest("quux(foo, bar, baz);", "WxWx","quux(foo, ar, az);"); + DoTest("foo\nbar\nbaz", "WxWx","foo\nar\naz"); + + // Testing "b" + DoTest("bar", "lbx", "ar"); + DoTest("foo bar baz", "2wbx", "foo ar baz"); + DoTest("foo bar", "w20bx","oo bar"); + DoTest("quux(foo, bar, baz);", "2W4l2bx2bx","quux(foo, ar, az);"); + DoTest("foo\nbar\nbaz", "WWbx","foo\nar\nbaz"); + + // Testing "B" + DoTest("bar", "lBx", "ar"); + DoTest("foo bar baz", "2wBx", "foo ar baz"); + DoTest("foo bar", "w20Bx","oo bar"); + DoTest("quux(foo, bar, baz);", "2W4lBBx","quux(foo, ar, baz);"); + DoTest("foo\nbar", "WlBx","foo\nar"); + + // Testing "e" + DoTest("quux(foo, bar, baz);", "exex2ex10ex","quu(fo, bar baz)"); + + // Testing "E" + DoTest("quux(foo, bar, baz);", "ExEx10Ex","quux(foo bar baz)"); + + // Testing "$" + DoTest("foo\nbar\nbaz", "$x3$x","fo\nbar\nba"); + + // Testing "0" + DoTest(" foo", "$0x","foo"); + + // Testing "#" + DoTest("1 1 1", "2#x","1 1"); + DoTest("foo bar foo bar", "#xlll#x","foo ar oo bar"); + DoTest("(foo (bar (foo( bar))))", "#xll#x","(foo (ar (oo( bar))))"); + + // Testing "*" + DoTest("(foo (bar (foo( bar))))", "*x","(foo (bar (oo( bar))))"); + + // Testing "-" + DoTest("0\n1\n2\n3\n4\n5", "5j-x2-x", "0\n1\n\n3\n\n5"); + + // Testing "^" + DoTest(" foo bar", "$^x", " oo bar"); + + // Testing "gg" + DoTest("1\n2\n3\n4\n5", "4jggx", "\n2\n3\n4\n5"); + + // Testing "G" + DoTest("1\n2\n3\n4\n5", "Gx", "1\n2\n3\n4\n"); + + // Testing "ge" + DoTest("quux(foo, bar, baz);", "9lgexgex$gex", "quux(fo bar, ba);"); + + // Testing "gE" + DoTest("quux(foo, bar, baz);", "9lgExgEx$gEx", "quux(fo bar baz);"); + + // Testing "|" + DoTest("123456789", "3|rx4|rx8|rx1|rx", "x2xx567x9"); + + // Testing "`" + DoTest("foo\nbar\nbaz", "lmaj`arx", "fxo\nbar\nbaz"); + + // Testing "'" + DoTest("foo\nbar\nbaz", "lmaj'arx", "xoo\nbar\nbaz"); + + // Testing "%" + DoTest("foo{\n}\n", "$d%", "foo\n"); + DoTest("FOO{\nBAR}BAZ", "lllgu%", "FOO{\nbar}BAZ"); + DoTest("foo{\nbar}baz", "lllgU%", "foo{\nBAR}baz"); + DoTest("foo{\nbar\n}", "llly%p", "foo{{\nbar\n}\nbar\n}"); + + // Testing percentage "%" + DoTest("10%\n20%\n30%\n40%\n50%\n60%\n70%\n80%\n90%\n100%", + "20%dd", + "10%\n30%\n40%\n50%\n60%\n70%\n80%\n90%\n100%"); + + DoTest("10%\n20%\n30%\n40%\n50%\n60%\n70%\n80%\n90%\n100%", + "50%dd", + "10%\n20%\n30%\n40%\n60%\n70%\n80%\n90%\n100%"); + + DoTest("10%\n20%\n30%\n40%\n50%\n60%\n70\n80%\n90%\n100%", + "65%dd", + "10%\n20%\n30%\n40%\n50%\n60%\n80%\n90%\n100%"); + + DoTest("10%\n20%\n30%\n40%\n50%\n60%\n70%\n80%\n90%\n100%", + "5j10%dd", + "20%\n30%\n40%\n50%\n60%\n70%\n80%\n90%\n100%"); + + // TEXT OBJECTS + DoTest( "foo \"bar baz ('first', 'second' or 'third')\"", + "8w2lci'", + "foo \"bar baz ('first', '' or 'third')\""); + + DoTest( "foo \"bar baz ('first', 'second' or 'third')\"", + "8w2lca'", + "foo \"bar baz ('first', or 'third')\""); + + DoTest( "foo \"bar baz ('first', 'second' or 'third')\"", + "8w2lci(", + "foo \"bar baz ()\""); + + DoTest( "foo \"bar baz ('first', 'second' or 'third')\"", + "8w2lci(", + "foo \"bar baz ()\""); + + DoTest( "foo \"bar baz ('first', 'second' or 'third')\"", + "8w2lcib", + "foo \"bar baz ()\""); + + DoTest( "foo \"bar baz ('first', 'second' or 'third')\"", + "8w2lca)", + "foo \"bar baz \""); + + DoTest( "foo \"bar baz ('first', 'second' or 'third')\"", + "8w2lci\"", + "foo \"\""); + + DoTest( "foo \"bar baz ('first', 'second' or 'third')\"", + "8w2lda\"", + "foo "); + + DoTest( "foo \"bar [baz ({'first', 'second'} or 'third')]\"", + "9w2lci[", + "foo \"bar []\""); + + DoTest( "foo \"bar [baz ({'first', 'second'} or 'third')]\"", + "9w2lci]", + "foo \"bar []\""); + + DoTest( "foo \"bar [baz ({'first', 'second'} or 'third')]\"", + "9w2lca[", + "foo \"bar \""); + + DoTest( "foo \"bar [baz ({'first', 'second'} or 'third')]\"", + "9w2lci{", + "foo \"bar [baz ({} or 'third')]\""); + + DoTest( "foo \"bar [baz ({'first', 'second'} or 'third')]\"", + "7w2lca}", + "foo \"bar [baz ( or 'third')]\""); + + DoTest( "{foo { bar { (baz) \"asd\" }} {1} {2} {3} {4} {5} }", + "ldiB", + "{}"); + + DoTest( "int main() {\n printf( \"HelloWorld!\\n\" );\n return 0;\n} ", + "jda}xr;", + "int main();"); + + DoTest("QList","wwldi>","QList<>"); + DoTest("QList","wwlda<","QList"); + DoTest("\nTitle\n", + "di", + "<>\n<>Title\n"); + + DoTest( "foo bar baz", "wldiw", "foo baz"); + + DoTest( "foo bar baz", "wldawx", "foo az"); + + DoTest( "foo ( \n bar\n)baz","jdi(", "foo ()baz"); + DoTest( "foo ( \n bar\n)baz","jda(", "foo baz"); + DoTest( "(foo(bar)baz)", "ldi)", "()"); + DoTest( "(foo(bar)baz)", "lca(", ""); + DoTest( "( foo ( bar ) )baz", "di(", "()baz" ); + DoTest( "( foo ( bar ) )baz", "da(", "baz" ); + DoTest( "[foo [ bar] [(a)b [c]d ]]","$hda]", "[foo [ bar] ]"); + + DoTest( "hi!))))}}]]","di]di}da)di)da]", "hi!))))}}]]" ); + + DoTest("foo \"bar\" baz", "4ldi\"", "foo \"\" baz"); + DoTest("foo \"bar\" baz", "8lca\"", "foo baz"); + + DoTest("foo 'bar' baz", "4lca'", "foo baz"); + DoTest("foo 'bar' baz", "8ldi'", "foo '' baz"); + + DoTest("foo `bar` baz", "4lca`", "foo baz"); + DoTest("foo `bar` baz", "8ldi`", "foo `` baz"); + + DoTest("()","di(","()"); + DoTest("\"\"","di\"","\"\""); + +} + +void ViModeTest::NormalModeCommandsTest() { + + // Testing "J" + DoTest("foo\nbar", "J", "foo bar"); + + // Testing "dd" + DoTest("foo\nbar", "dd", "bar"); + DoTest("foo\nbar", "2dd", ""); + DoTest("foo\nbar\n", "Gdd", "foo\nbar"); + + // Testing "D" + DoTest("foo bar", "lllD", "foo"); + DoTest("foo\nfoo2\nfoo3", "l2D", "f\nfoo3"); + + // Testing "d" + DoTest("foobar", "ld2l", "fbar"); + DoTest("1 2 3\n4 5 6", "ld100l", "1\n4 5 6"); + + DoTest("123\n", "d10l", "\n"); + DoTest("123\n", "10lx", "12\n"); + + // Testing "X" + DoTest("ABCD", "$XX", "AD"); + + // Testing "gu" + DoTest("FOO\nBAR BAZ", "guj", "foo\nbar baz"); + DoTest("AbCDF", "gu3l", "abcDF"); + + // Testing "guu" + DoTest("FOO", "guu", "foo"); + DoTest("FOO\nBAR\nBAZ", "2guu", "foo\nbar\nBAZ"); + + + // Testing "gU" + DoTest("aBcdf", "gU2l", "ABcdf"); + DoTest("foo\nbar baz", "gUj", "FOO\nBAR BAZ"); + + // Testing "gUU" + DoTest("foo", "gUU", "FOO"); + DoTest("foo\nbar\nbaz", "2gUU", "FOO\nBAR\nbaz"); + + // Testing "Ctrl-o" and "Ctrl-i" + DoTest("abc\ndef\nghi","Gx\\ctrl-ox","bc\ndef\nhi"); + DoTest("{\n}","%\\ctrl-ox","\n}"); + DoTest("Foo foo.\nBar bar.\nBaz baz.", + "lmajlmb`a`b\\ctrl-ox", + "Fo foo.\nBar bar.\nBaz baz."); + DoTest("Foo foo.\nBar bar.\nBaz baz.", + "lmajlmb`a`bj\\ctrl-o\\ctrl-ix", + "Foo foo.\nBar bar.\nBa baz."); + + + // Testing "gq" (reformat) text + DoTest("foo\nbar", "gqq", "foo\nbar"); + DoTest("foo\nbar", "2gqq", "foo bar"); + DoTest("foo\nbar\nbaz", "jgqj", "foo\nbar baz"); + + // when setting the text to wrap at column 10, this should be re-formatted to + // span several lines ... + kate_document->setWordWrapAt( 10 ); + DoTest("foo bar foo bar foo bar", "gqq", "foo bar\nfoo bar\nfoo bar"); + + // ... and when re-setting it to column 80 again, they should be joined again + kate_document->setWordWrapAt( 80 ); + DoTest("foo bar\nfoo bar\nfoo bar", "gqG", "foo bar foo bar foo bar"); + + // test >> and << (indent and de-indent) + kate_document->config()->setReplaceTabsDyn(true); + + DoTest("foo\nbar", ">>", " foo\nbar"); + DoTest("foo\nbar", "2>>", " foo\n bar"); + DoTest("foo\nbar", "100>>", " foo\n bar"); +} + + +void ViModeTest::NormalModeControlTests() { + // Testing "Ctrl-x" + DoTest("150", "101\\ctrl-x", "49"); + DoTest("1", "\\ctrl-x\\ctrl-x\\ctrl-x\\ctrl-x", "-3"); + DoTest("0xabcdef", "1000000\\ctrl-x","0x9c8baf" ); + + // Testing "Ctrl-a" + DoTest("150", "101\\ctrl-a", "251"); + DoTest("1000", "\\ctrl-ax", "100"); + DoTest("-1", "1\\ctrl-a", "0"); + DoTest("-1", "l1\\ctrl-a", "0"); + + // Testing "Ctrl-r" + DoTest("foobar", "d3lu\\ctrl-r", "bar"); + DoTest("line 1\nline 2\n","ddu\\ctrl-r","line 2\n"); +} + +void ViModeTest::NormalModeNotYetImplementedFeaturesTest() { + // Testing "))" +// DoTest("Foo foo. Bar bar.","))\\ctrl-ox","Foo foo. ar bar."); +// DoTest("Foo foo.\nBar bar.\nBaz baz.",")))\\ctrl-ox\\ctrl-ox", "Foo foo.\nar bar.\nBaz baz."); +// DoTest("Foo foo.\nBar bar.\nBaz baz.","))\\ctrl-ox\\ctrl-ix","Foo foo.\nBar bar.\naz baz."); +// DoTest("Foo foo.\nBar bar.\nBaz baz.","))\\ctrl-ox\\ctrl-ix","Foo foo.\nBar bar.\naz baz."); + +} + +void ViModeTest::CommandModeTests() { + // Testing ":" + DoTest("foo\nbar\nbaz","\\:2\\x","foo\nar\nbaz"); + DoTest("foo\nbar\nbaz","jmak\\:'a\\x","foo\nar\nbaz"); + DoTest("foo\nbar\nbaz","\\:$\\x","foo\nbar\naz"); + + // Testing ":s" (sed) + DoTest("foo","\\:s/foo/bar\\","bar"); + DoTest("foobarbaz","\\:s/bar/xxx\\","fooxxxbaz"); + DoTest("foo","\\:s/bar/baz\\","foo"); + DoTest("foo\nfoo\nfoo","j\\:s/foo/bar\\", "foo\nbar\nfoo"); + DoTest("foo\nfoo\nfoo","2jma2k\\:'a,'as/foo/bar\\", "foo\nfoo\nbar"); + DoTest("foo\nfoo\nfoo","\\:%s/foo/bar\\","bar\nbar\nbar"); + DoTest("foo\nfoo\nfoo","\\:2,3s/foo/bar\\","foo\nbar\nbar"); + DoTest("foo\nfoo\nfoo\nfoo", "j2lmajhmbgg\\:'a,'bs/foo/bar\\","foo\nbar\nbar\nfoo"); + DoTest("foo\nfoo\nfoo\nfoo", "jlma2jmbgg\\:'b,'as/foo/bar\\","foo\nbar\nbar\nbar"); + DoTest("foo", "\\:s/$/x/g\\","foox"); + DoTest("foo", "\\:s/.*/x/g\\","x"); + + + DoTest("foo\nfoo\nfoo","\\:2s/foo/bar\\", "foo\nbar\nfoo"); + DoTest("foo\nfoo\nfoo","2jmagg\\:'as/foo/bar\\","foo\nfoo\nbar"); + DoTest("foo\nfoo\nfoo", "\\:$s/foo/bar\\","foo\nfoo\nbar"); + + // Testing ":d", ":delete" + DoTest("foo\nbar\nbaz","\\:2d\\","foo\nbaz"); + DoTest("foo\nbar\nbaz","\\:%d\\",""); + DoTest("foo\nbar\nbaz","\\:$d\\\\:$d\\","foo"); + DoTest("foo\nbar\nbaz","ma\\:2,'ad\\","baz"); + DoTest("foo\nbar\nbaz","\\:/foo/,/bar/d\\","baz"); + DoTest("foo\nbar\nbaz","\\:2,3delete\\","foo"); + + DoTest("foo\nbar\nbaz","\\:d\\","bar\nbaz"); + DoTest("foo\nbar\nbaz","\\:d 33\\",""); + DoTest("foo\nbar\nbaz","\\:3d a\\k\"ap","foo\nbaz\nbar"); + + // Testing ":y", ":yank" + DoTest("foo\nbar\nbaz","\\:3y\\p","foo\nbaz\nbar\nbaz"); + DoTest("foo\nbar\nbaz","\\:2y a 2\\\"ap","foo\nbar\nbaz\nbar\nbaz"); + DoTest("foo\nbar\nbaz","\\:y\\p","foo\nfoo\nbar\nbaz"); + DoTest("foo\nbar\nbaz","\\:3,1y\\p","foo\nfoo\nbar\nbaz\nbar\nbaz"); + + // Testing ">" + DoTest("foo","\\:>\\"," foo"); + DoTest(" foo","\\:<\\"," foo"); + + // Testing ":c", ":change" + DoTest("foo\nbar\nbaz","\\:2change\\","foo\n\nbaz"); + DoTest("foo\nbar\nbaz","\\:%c\\",""); + DoTest("foo\nbar\nbaz","\\:$c\\\\:$change\\","foo\nbar\n"); + DoTest("foo\nbar\nbaz","ma\\:2,'achange\\","\nbaz"); + DoTest("foo\nbar\nbaz","\\:2,3c\\","foo\n"); + + // Testing ":j" + DoTest("1\n2\n3\n4\n5","\\:2,4j\\","1\n2 3 4\n5"); + + + DoTest("1\n2\n3\n4","jvj\\ctrl-c\\:'<,'>d\\","1\n4"); + DoTest("1\n2\n3\n4","\\:1+1+1+1d\\","1\n2\n3"); + DoTest("1\n2\n3\n4","2j\\:.,.-1d\\","1\n4"); + DoTest("1\n2\n3\n4","\\:.+200-100-100+20-5-5-5-5+.-.,$-1+1-2+2-3+3-4+4-5+5-6+6-7+7-1000+1000+0-0-$+$-.+.-1d\\","4"); + DoTest("1\n2\n3\n4","majmbjmcjmdgg\\:'a+'b+'d-'c,.d\\",""); + + // Testing "{" and "}" motions + DoTest("","{}",""); + DoTest("foo","{}dd",""); + DoTest("foo\n\nbar","}dd","foo\nbar"); + DoTest("foo\n\nbar\n\nbaz","3}x","foo\n\nbar\n\nba"); + DoTest("foo\n\nbar\n\nbaz","3}{dd{dd","foo\nbar\nbaz"); + DoTest("foo\nfoo\n\nbar\n\nbaz","5}{dd{dd","foo\nfoo\nbar\nbaz"); + DoTest("foo\nfoo\n\nbar\n\nbaz","5}3{x","oo\nfoo\n\nbar\n\nbaz"); + DoTest("foo\n\n\nbar","10}{{x","oo\n\n\nbar"); + DoTest("foo\n\n\nbar","}}x","foo\n\n\nba"); + DoTest("foo\n\n\nbar\n","}}dd","foo\n\n\nbar"); +} + +// kate: space-indent on; indent-width 2; replace-tabs on; diff --git a/share/tests/vimode_test.h b/share/tests/vimode_test.h new file mode 100644 index 0000000..83dc208 --- /dev/null +++ b/share/tests/vimode_test.h @@ -0,0 +1,62 @@ +/* This file is part of the KDE libraries + + Copyright (C) 2011 Kuzmich Svyatoslav + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. +*/ + +#ifndef VIMODE_TEST_H +#define VIMODE_TEST_H + +#include + +#include +#include +#include + +class ViModeTest : public QObject +{ + Q_OBJECT + +public: + ViModeTest(); + ~ViModeTest(); + +private Q_SLOTS: + void NormalModeFallingTests(); + void NormalModeMotionsTest(); + void NormalModeCommandsTest(); + void NormalModeControlTests(); + void NormalModeNotYetImplementedFeaturesTest(); + + void InsertModeTests(); + void VisualModeTests(); + void CommandModeTests(); + + +private: + void TestPressKey(QString str); + void DoTest(QString original_text, + QString command, + QString expected_text); + + KateDocument *kate_document; + KateView *kate_view; + KateViInputModeManager *vi_input_mode_manager; +}; + +#endif + +// kate: space-indent on; indent-width 2; replace-tabs on;