• Skip to content
  • Skip to link menu
KDE 4.3 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

Kate

katecmds.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2003 - 2005 Anders Lund <anders@alweb.dk>
00003    Copyright (C) 2001-2004 Christoph Cullmann <cullmann@kde.org>
00004    Copyright (C) 2001 Charles Samuels <charles@kde.org>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License version 2 as published by the Free Software Foundation.
00009 
00010    This library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Library General Public License for more details.
00014 
00015    You should have received a copy of the GNU Library General Public License
00016    along with this library; see the file COPYING.LIB.  If not, write to
00017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00018    Boston, MA 02110-1301, USA.
00019 */
00020 
00021 #include "katecmds.h"
00022 
00023 #include "katedocument.h"
00024 #include "kateview.h"
00025 #include "kateconfig.h"
00026 #include "kateautoindent.h"
00027 #include "katetextline.h"
00028 #include "katesyntaxmanager.h"
00029 #include "kateglobal.h"
00030 #include "katerenderer.h"
00031 #include "katecmd.h"
00032 
00033 #include <kdebug.h>
00034 #include <klocale.h>
00035 #include <kurl.h>
00036 #include <kshellcompletion.h>
00037 
00038 #include <QtCore/QRegExp>
00039 
00040 //BEGIN CoreCommands
00041 // syncs a config flag in the document with a boolean value
00042 static void setDocFlag( KateDocumentConfig::ConfigFlags flag, bool enable,
00043                   KateDocument *doc )
00044 {
00045   doc->config()->setConfigFlags( flag, enable );
00046 }
00047 
00048 // this returns wheather the string s could be converted to
00049 // a bool value, one of on|off|1|0|true|false. the argument val is
00050 // set to the extracted value in case of success
00051 static bool getBoolArg( const QString &t, bool *val  )
00052 {
00053   bool res( false );
00054   QString s = t.toLower();
00055   res = (s == "on" || s == "1" || s == "true");
00056   if ( res )
00057   {
00058     *val = true;
00059     return true;
00060   }
00061   res = (s == "off" || s == "0" || s == "false");
00062   if ( res )
00063   {
00064     *val = false;
00065     return true;
00066   }
00067   return false;
00068 }
00069 
00070 const QStringList &KateCommands::CoreCommands::cmds()
00071 {
00072   static QStringList l;
00073 
00074   if (l.isEmpty())
00075   l << "indent" << "unindent" << "cleanindent"
00076     << "comment" << "uncomment" << "goto" << "kill-line"
00077     << "set-tab-width" << "set-replace-tabs" << "set-show-tabs"
00078     << "set-remove-trailing-space"
00079     << "set-indent-width"
00080     << "set-indent-mode" << "set-auto-indent"
00081     << "set-line-numbers" << "set-folding-markers" << "set-icon-border"
00082     << "set-wrap-cursor"
00083     << "set-word-wrap" << "set-word-wrap-column"
00084     << "set-replace-tabs-save" << "set-remove-trailing-space-save"
00085     << "set-highlight" << "set-mode" << "set-show-indent"
00086     << "print";
00087 
00088   return l;
00089 }
00090 
00091 bool KateCommands::CoreCommands::exec(KTextEditor::View *view,
00092                             const QString &_cmd,
00093                             QString &errorMsg)
00094 {
00095   return exec( view, _cmd, errorMsg, KTextEditor::Range::invalid() );
00096 }
00097 
00098 bool KateCommands::CoreCommands::exec(KTextEditor::View *view,
00099                             const QString &_cmd,
00100                             QString &errorMsg,
00101                             const KTextEditor::Range& range)
00102 {
00103 #define KCC_ERR(s) { errorMsg=s; return false; }
00104   // cast it hardcore, we know that it is really a kateview :)
00105   KateView *v = (KateView*) view;
00106 
00107   if ( ! v )
00108     KCC_ERR( i18n("Could not access view") );
00109 
00110   //create a list of args
00111   QStringList args(_cmd.split( QRegExp("\\s+"), QString::SkipEmptyParts)) ;
00112   QString cmd ( args.takeFirst() );
00113 
00114   // ALL commands that takes no arguments.
00115   if ( cmd == "indent" )
00116   {
00117     if ( range.isValid() ) {
00118       v->doc()->editStart();
00119       for ( int line = range.start().line(); line <= range.end().line(); line++ ) {
00120         v->doc()->indent( v, line, 1 );
00121       }
00122       v->doc()->editEnd();
00123     } else {
00124       v->indent();
00125     }
00126     return true;
00127   }
00128 #if 0
00129   else if ( cmd == "run-myself" )
00130   {
00131 #ifndef Q_WS_WIN //todo
00132     return KateGlobal::self()->jscript()->execute(v, v->doc()->text(), errorMsg);
00133 #else
00134     return 0;
00135 #endif
00136   }
00137 #endif
00138   else if ( cmd == "unindent" )
00139   {
00140     if ( range.isValid() ) {
00141       v->doc()->editStart();
00142       for ( int line = range.start().line(); line <= range.end().line(); line++ ) {
00143         v->doc()->indent( v, line, -1 );
00144       }
00145       v->doc()->editEnd();
00146     } else {
00147       v->unIndent();
00148     }
00149     return true;
00150   }
00151   else if ( cmd == "cleanindent" )
00152   {
00153     if ( range.isValid() ) {
00154       v->doc()->editStart();
00155       for ( int line = range.start().line(); line <= range.end().line(); line++ ) {
00156         v->doc()->indent( v, line, 0 );
00157       }
00158       v->doc()->editEnd();
00159     } else {
00160       v->cleanIndent();
00161     }
00162     return true;
00163   }
00164   else if ( cmd == "comment" )
00165   {
00166     if ( range.isValid() ) {
00167       v->doc()->editStart();
00168       for ( int line = range.start().line(); line <= range.end().line(); line++ ) {
00169         v->doc()->comment( v, line, 0, 1 );
00170       }
00171       v->doc()->editEnd();
00172     } else {
00173       v->comment();
00174     }
00175     return true;
00176   }
00177   else if ( cmd == "uncomment" )
00178   {
00179     if ( range.isValid() ) {
00180       v->doc()->editStart();
00181       for ( int line = range.start().line(); line <= range.end().line(); line++ ) {
00182         v->doc()->comment( v, line, 0, -1 );
00183       }
00184       v->doc()->editEnd();
00185     } else {
00186       v->uncomment();
00187     }
00188     return true;
00189   }
00190   else if ( cmd == "kill-line" )
00191   {
00192     if ( range.isValid() ) {
00193       v->doc()->editStart();
00194       for ( int line = range.start().line(); line <= range.end().line(); line++ ) {
00195         v->doc()->removeLine( range.start().line() );
00196       }
00197       v->doc()->editEnd();
00198     } else {
00199       v->killLine();
00200     }
00201     return true;
00202   }
00203   else if ( cmd == "print" )
00204   {
00205     v->doc()->printDialog();
00206     return true;
00207   }
00208 
00209   // ALL commands that take a string argument
00210   else if ( cmd == "set-indent-mode" ||
00211             cmd == "set-highlight" ||
00212             cmd == "set-mode" )
00213   {
00214     // need at least one item, otherwise args.first() crashes
00215     if ( ! args.count() )
00216       KCC_ERR( i18n("Missing argument. Usage: %1 <value>",  cmd ) );
00217 
00218     if ( cmd == "set-indent-mode" )
00219     {
00220       v->doc()->config()->setIndentationMode( args.first() );
00221       return true;
00222     }
00223     else if ( cmd == "set-highlight" )
00224     {
00225       if ( v->doc()->setHighlightingMode( args.first()) )
00226       {
00227         ((KateDocument*)v->doc())->setDontChangeHlOnSave ();
00228         return true;
00229       }
00230 
00231       KCC_ERR( i18n("No such highlighting '%1'",  args.first() ) );
00232     }
00233     else if ( cmd == "set-mode" )
00234     {
00235       if ( v->doc()->setMode( args.first()) )
00236         return true;
00237 
00238       KCC_ERR( i18n("No such mode '%1'",  args.first() ) );
00239     }
00240   }
00241   // ALL commands that takes exactly one integer argument.
00242   else if ( cmd == "set-tab-width" ||
00243             cmd == "set-indent-width" ||
00244             cmd == "set-word-wrap-column" ||
00245             cmd == "goto" )
00246   {
00247     // find a integer value > 0
00248     if ( ! args.count() )
00249       KCC_ERR( i18n("Missing argument. Usage: %1 <value>",  cmd ) );
00250     bool ok;
00251     int val ( args.first().toInt( &ok, 10 ) ); // use base 10 even if the string starts with '0'
00252     if ( !ok )
00253       KCC_ERR( i18n("Failed to convert argument '%1' to integer.",
00254                   args.first() ) );
00255 
00256     if ( cmd == "set-tab-width" )
00257     {
00258       if ( val < 1 )
00259         KCC_ERR( i18n("Width must be at least 1.") );
00260       v->doc()->config()->setTabWidth( val );
00261     }
00262     else if ( cmd == "set-indent-width" )
00263     {
00264       if ( val < 1 )
00265         KCC_ERR( i18n("Width must be at least 1.") );
00266       v->doc()->config()->setIndentationWidth( val );
00267     }
00268     else if ( cmd == "set-word-wrap-column" )
00269     {
00270       if ( val < 2 )
00271         KCC_ERR( i18n("Column must be at least 1.") );
00272       v->doc()->setWordWrapAt( val );
00273     }
00274     else if ( cmd == "goto" )
00275     {
00276       if ( args.first().at(0) == '-' || args.first().at(0) == '+' ) {
00277         // if the number starts with a minus or plus sign, add/subract the number
00278         val = v->cursorPosition().line() + val;
00279       } else {
00280         val--; // convert given line number to the internal representation of line numbers
00281       }
00282 
00283       // constrain cursor to the range [0, number of lines]
00284       if ( val < 0 ) {
00285         val = 0;
00286       } else if ( val > v->doc()->lines()-1 ) {
00287         val = v->doc()->lines()-1;
00288       }
00289 
00290       v->setCursorPosition( KTextEditor::Cursor( val, 0 ) );
00291       return true;
00292     }
00293     return true;
00294   }
00295 
00296   // ALL commands that takes 1 boolean argument.
00297   else if ( cmd == "set-icon-border" ||
00298             cmd == "set-folding-markers" ||
00299             cmd == "set-line-numbers" ||
00300             cmd == "set-replace-tabs" ||
00301             cmd == "set-remove-trailing-space" ||
00302             cmd == "set-show-tabs" ||
00303             cmd == "set-word-wrap" ||
00304             cmd == "set-wrap-cursor" ||
00305             cmd == "set-replace-tabs-save" ||
00306             cmd == "set-remove-trailing-space-save" ||
00307             cmd == "set-show-indent" )
00308   {
00309     if ( ! args.count() )
00310       KCC_ERR( i18n("Usage: %1 on|off|1|0|true|false",  cmd ) );
00311     bool enable = false;
00312     if ( getBoolArg( args.first(), &enable ) )
00313     {
00314       if ( cmd == "set-icon-border" )
00315         v->setIconBorder( enable );
00316       else if (cmd == "set-folding-markers")
00317         v->setFoldingMarkersOn( enable );
00318       else if ( cmd == "set-line-numbers" )
00319         v->setLineNumbersOn( enable );
00320       else if ( cmd == "set-show-indent" )
00321         v->renderer()->setShowIndentLines( enable );
00322       else if ( cmd == "set-replace-tabs" )
00323         setDocFlag( KateDocumentConfig::cfReplaceTabsDyn, enable, v->doc() );
00324       else if ( cmd == "set-remove-trailing-space" )
00325         setDocFlag( KateDocumentConfig::cfRemoveTrailingDyn, enable, v->doc() );
00326       else if ( cmd == "set-show-tabs" )
00327         setDocFlag( KateDocumentConfig::cfShowTabs, enable, v->doc() );
00328       else if ( cmd == "set-show-trailing-spaces" )
00329         setDocFlag( KateDocumentConfig::cfShowSpaces, enable, v->doc() );
00330       else if ( cmd == "set-word-wrap" )
00331         v->doc()->setWordWrap( enable );
00332       else if ( cmd == "set-remove-trailing-space-save" )
00333         setDocFlag( KateDocumentConfig::cfRemoveSpaces, enable, v->doc() );
00334       else if ( cmd == "set-wrap-cursor" )
00335         setDocFlag( KateDocumentConfig::cfWrapCursor, enable, v->doc() );
00336 
00337       return true;
00338     }
00339     else
00340       KCC_ERR( i18n("Bad argument '%1'. Usage: %2 on|off|1|0|true|false",
00341                  args.first() ,  cmd ) );
00342   }
00343 
00344   // unlikely..
00345   KCC_ERR( i18n("Unknown command '%1'", cmd) );
00346 }
00347 
00348 bool KateCommands::CoreCommands::supportsRange(const QString &range)
00349 {
00350   static QStringList l;
00351 
00352   if (l.isEmpty())
00353   l << "indent" << "unindent" << "cleanindent"
00354     << "comment" << "uncomment" << "kill-line";
00355 
00356   return l.contains(range);
00357 }
00358 
00359 KCompletion *KateCommands::CoreCommands::completionObject( KTextEditor::View *view, const QString &cmd )
00360 {
00361   Q_UNUSED(view)
00362 
00363   if ( cmd == "set-highlight" )
00364   {
00365     QStringList l;
00366     for ( int i = 0; i < KateHlManager::self()->highlights(); i++ )
00367       l << KateHlManager::self()->hlName (i);
00368 
00369     KateCmdShellCompletion *co = new KateCmdShellCompletion();
00370     co->setItems( l );
00371     co->setIgnoreCase( true );
00372     return co;
00373   }
00374   return 0L;
00375 }
00376 //END CoreCommands
00377 
00378 // BEGIN ViCommands
00379 const QStringList &KateCommands::ViCommands::cmds()
00380 {
00381   static QStringList l;
00382 
00383   if (l.isEmpty())
00384   l << "w" << "hardcopy" << "nnoremap" << "nn";
00385 
00386   return l;
00387 }
00388 
00389 bool KateCommands::ViCommands::exec(KTextEditor::View *view,
00390                             const QString &_cmd,
00391                             QString &msg)
00392 {
00393   return exec( view, _cmd, msg, KTextEditor::Range::invalid() );
00394 }
00395 
00396 bool KateCommands::ViCommands::exec(KTextEditor::View *view,
00397                             const QString &_cmd,
00398                             QString &msg,
00399                             const KTextEditor::Range& range)
00400 {
00401   Q_UNUSED(range)
00402   // cast it hardcore, we know that it is really a kateview :)
00403   KateView *v = (KateView*) view;
00404 
00405   if ( !v ) {
00406     msg = i18n("Could not access view");
00407     return false;
00408   }
00409 
00410   //create a list of args
00411   QStringList args(_cmd.split( QRegExp("\\s+"), QString::SkipEmptyParts)) ;
00412   QString cmd ( args.takeFirst() );
00413 
00414   // ALL commands that takes no arguments.
00415   if ( cmd == "w" )
00416   {
00417     v->doc()->documentSave();
00418     return true;
00419   }
00420   else if ( cmd == "hardcopy" )
00421   {
00422     v->doc()->printDialog();
00423     return true;
00424   }
00425   else if ( cmd == "nnoremap" || cmd == "nn" )
00426   {
00427     if ( args.count() == 1 ) {
00428       msg = v->getViInputModeManager()->getMapping( NormalMode, args.at( 0 ) );
00429       if ( msg.isEmpty() ) {
00430         msg = i18n( "No mapping found for \"%1\"", args.at(0) );
00431         return false;
00432       } else {
00433         msg = i18n( "\"%1\" is mapped to \"%2\"", args.at( 0 ), msg );
00434       }
00435     } else if ( args.count() == 2 ) {
00436       v->getViInputModeManager()->addMapping( NormalMode, args.at( 0 ), args.at( 1 ) );
00437     } else {
00438       msg = i18n("Missing argument(s). Usage: %1 <from> [<to>]",  cmd );
00439       return false;
00440     }
00441 
00442     return true;
00443   }
00444 
00445   // should not happen :)
00446   msg = i18n("Unknown command '%1'", cmd);
00447   return false;
00448 }
00449 
00450 bool KateCommands::ViCommands::supportsRange(const QString &range)
00451 {
00452   Q_UNUSED(range)
00453   return false; // no commands support a range yet
00454 }
00455 
00456 KCompletion *KateCommands::ViCommands::completionObject( KTextEditor::View *view, const QString &cmd )
00457 {
00458   Q_UNUSED(view)
00459 
00460   KateView *v = (KateView*) view;
00461 
00462   if ( v && ( cmd == "nn" || cmd == "nnoremap" ) )
00463   {
00464     QStringList l = v->getViInputModeManager()->getMappings( NormalMode );
00465 
00466     KateCmdShellCompletion *co = new KateCmdShellCompletion();
00467     co->setItems( l );
00468     co->setIgnoreCase( false );
00469     return co;
00470   }
00471   return 0L;
00472 }
00473 //END ViCommands
00474 
00475 //BEGIN SedReplace
00476 static void replace(QString &s, const QString &needle, const QString &with)
00477 {
00478   int pos=0;
00479   while (1)
00480   {
00481     pos=s.indexOf(needle, pos);
00482     if (pos==-1) break;
00483     s.replace(pos, needle.length(), with);
00484     pos+=with.length();
00485   }
00486 
00487 }
00488 
00489 static int backslashString(const QString &haystack, const QString &needle, int index)
00490 {
00491   int len=haystack.length();
00492   int searchlen=needle.length();
00493   bool evenCount=true;
00494   while (index<len)
00495   {
00496     if (haystack[index]=='\\')
00497     {
00498       evenCount=!evenCount;
00499     }
00500     else
00501     {  // isn't a slash
00502       if (!evenCount)
00503       {
00504         if (haystack.mid(index, searchlen)==needle)
00505           return index-1;
00506       }
00507       evenCount=true;
00508     }
00509     index++;
00510 
00511   }
00512 
00513   return -1;
00514 }
00515 
00516 // exchange "\t" for the actual tab character, for example
00517 static void exchangeAbbrevs(QString &str)
00518 {
00519   // the format is (findreplace)*[nullzero]
00520   const char *magic="a\x07t\tn\n";
00521 
00522   while (*magic)
00523   {
00524     int index=0;
00525     char replace=magic[1];
00526     while ((index=backslashString(str, QString (QChar::fromAscii(*magic)), index))!=-1)
00527     {
00528       str.replace(index, 2, QChar(replace));
00529       index++;
00530     }
00531     magic++;
00532     magic++;
00533   }
00534 }
00535 
00536 int KateCommands::SedReplace::sedMagic( KateDocument *doc, int &line,
00537                                         const QString &find, const QString &repOld, const QString &delim,
00538                                         bool noCase, bool repeat,
00539                                         uint startcol, int endcol )
00540 {
00541   KateTextLine::Ptr ln = doc->kateTextLine( line );
00542   if ( ! ln || ! ln->length() ) return 0;
00543 
00544   // HANDLING "\n"s in PATTERN
00545   // * Create a list of patterns, splitting PATTERN on (unescaped) "\n"
00546   // * insert $s and ^s to match line ends/beginnings
00547   // * When matching patterhs after the first one, replace \N with the captured
00548   //   text.
00549   // * If all patterns in the list match sequentiel lines, there is a match, so
00550   // * remove line/start to line + patterns.count()-1/patterns.last.length
00551   // * handle capatures by putting them in one list.
00552   // * the existing insertion is fine, including the line calculation.
00553 
00554   QStringList patterns(find.split( QRegExp("(^\\\\n|(?![^\\\\])\\\\n)"), QString::KeepEmptyParts));
00555   if ( patterns.count() > 1 )
00556   {
00557     for ( int i = 0; i < patterns.count(); i++ )
00558     {
00559       if ( i < patterns.count() - 1 )
00560         patterns[i].append("$");
00561       if ( i )
00562         patterns[i].prepend("^");
00563 
00564        kDebug(13025)<<"patterns["<<i<<"] ="<<patterns[i];
00565     }
00566   }
00567 
00568   QRegExp matcher(patterns[0], noCase ?Qt::CaseSensitive:Qt::CaseInsensitive);
00569 
00570   uint len;
00571   int matches = 0;
00572 
00573   while ( ln->searchText( startcol, matcher, &startcol, &len ) )
00574   {
00575 
00576     if ( endcol >= 0  && startcol + len > (uint)endcol )
00577       break;
00578 
00579     matches++;
00580 
00581 
00582     QString rep=repOld;
00583 
00584     // now set the backreferences in the replacement
00585     const QStringList backrefs=matcher.capturedTexts();
00586     int refnum=1;
00587 
00588     QStringList::ConstIterator i = backrefs.begin();
00589     ++i;
00590 
00591     for (; i!=backrefs.end(); ++i)
00592     {
00593       // I need to match "\\" or "", but not "\"
00594       QString number=QString::number(refnum);
00595 
00596       int index=0;
00597       while (index!=-1)
00598       {
00599         index=backslashString(rep, number, index);
00600         if (index>=0)
00601         {
00602           rep.replace(index, 2, *i);
00603           index+=(*i).length();
00604         }
00605       }
00606 
00607       refnum++;
00608     }
00609 
00610     replace(rep, "\\\\", "\\");
00611     replace(rep, "\\" + delim, delim);
00612 
00613     doc->removeText( KTextEditor::Range (line, startcol, line, startcol + len) );
00614     doc->insertText( KTextEditor::Cursor (line, startcol), rep );
00615 
00616     // TODO if replace contains \n,
00617     // change the line number and
00618     // check for text that needs be searched behind the last inserted newline.
00619     int lns = rep.count(QChar::fromLatin1('\n'));
00620     if ( lns > 0 )
00621     {
00622       line += lns;
00623 
00624       if ( doc->lineLength( line ) > 0 && ( endcol < 0 || (uint)endcol  >= startcol + len ) )
00625       {
00626       //  if ( endcol  >= startcol + len )
00627           endcol -= (startcol + len);
00628           uint sc = rep.length() - rep.lastIndexOf('\n') - 1;
00629         matches += sedMagic( doc, line, find, repOld, delim, noCase, repeat, sc, endcol );
00630       }
00631     }
00632 
00633     if (!repeat) break;
00634     startcol+=rep.length();
00635 
00636     // sanity check -- avoid infinite loops eg with %s,.*,,g ;)
00637     uint ll = ln->length();
00638     if ( ! ll || startcol > ll )
00639       break;
00640   }
00641 
00642   return matches;
00643 }
00644 
00645 bool KateCommands::SedReplace::exec (KTextEditor::View *view, const QString &cmd, QString &msg)
00646 {
00647   return exec(view, cmd, msg, KTextEditor::Range::invalid());
00648 }
00649 
00650 bool KateCommands::SedReplace::exec (class KTextEditor::View *view, const QString &cmd,
00651     QString &msg, const KTextEditor::Range &r)
00652 {
00653   kDebug(13025)<<"SedReplace::execCmd( "<<cmd<<" )";
00654   if (r.isValid())
00655     kDebug(13025)<<"Range: " << r;
00656 
00657   QRegExp delim("^s\\s*([^\\w\\s])");
00658   if ( delim.indexIn( cmd ) < 0 ) return false;
00659 
00660   bool noCase=cmd[cmd.length()-1]=='i' || cmd[cmd.length()-2]=='i';
00661   bool repeat=cmd[cmd.length()-1]=='g' || cmd[cmd.length()-2]=='g';
00662 
00663   QString d = delim.cap(1);
00664   kDebug(13025)<<"SedReplace: delimiter is '"<<d<<"'";
00665 
00666   QRegExp splitter( QString("^s\\s*")  + d + "((?:[^\\\\\\" + d + "]|\\\\.)*)\\"
00667       + d +"((?:[^\\\\\\" + d + "]|\\\\.)*)(\\" + d + "[ig]{0,2})?$" );
00668   if (splitter.indexIn(cmd)<0) return false;
00669 
00670   QString find=splitter.cap(1);
00671   kDebug(13025)<< "SedReplace: find=" << find;
00672 
00673   QString replace=splitter.cap(2);
00674   exchangeAbbrevs(replace);
00675   kDebug(13025)<< "SedReplace: replace=" << replace;
00676 
00677   if ( find.contains("\\n") )
00678   {
00679     // FIXME: make replacing newlines work
00680     msg = i18n("Sorry, but Kate is not able to replace newlines, yet");
00681     return false;
00682   }
00683 
00684   KateDocument *doc = ((KateView*)view)->doc();
00685   if ( ! doc ) return false;
00686 
00687   doc->editStart();
00688 
00689   int replacementsDone = 0;
00690   int linesTouched = 0;
00691 
00692   if (r.isValid()) { // given range
00693     for (int line = r.start().line(); line <= r.end().line(); line++) {
00694       int temp = replacementsDone;
00695       replacementsDone += sedMagic( doc, line, find, replace, d, !noCase, repeat );
00696       if (replacementsDone > temp) {
00697         linesTouched++;
00698       }
00699     }
00700   } else { // current line
00701     int line= view->cursorPosition().line();
00702     replacementsDone += sedMagic(doc, line, find, replace, d, !noCase, repeat);
00703     if (replacementsDone > 0) {
00704       linesTouched = 1;
00705     }
00706   }
00707 
00708   msg = i18ncp("%2 is the translation of the next message",
00709                "1 replacement done on %2", "%1 replacements done on %2", replacementsDone,
00710                i18ncp("substituted into the previous message",
00711                       "1 line", "%1 lines", linesTouched));
00712 
00713   doc->editEnd();
00714 
00715   return true;
00716 }
00717 
00718 //END SedReplace
00719 
00720 //BEGIN Character
00721 bool KateCommands::Character::exec (KTextEditor::View *view, const QString &_cmd, QString &)
00722 {
00723   QString cmd = _cmd;
00724 
00725   // hex, octal, base 9+1
00726   QRegExp num("^char *(0?x[0-9A-Fa-f]{1,4}|0[0-7]{1,6}|[0-9]{1,5})$");
00727   if (num.indexIn(cmd)==-1) return false;
00728 
00729   cmd=num.cap(1);
00730 
00731   // identify the base
00732 
00733   unsigned short int number=0;
00734   int base=10;
00735   if (cmd[0]=='x' || cmd.startsWith(QLatin1String("0x")))
00736   {
00737     cmd.remove(QRegExp("^0?x"));
00738     base=16;
00739   }
00740   else if (cmd[0]=='0')
00741     base=8;
00742   bool ok;
00743   number=cmd.toUShort(&ok, base);
00744   if (!ok || number==0) return false;
00745   if (number<=255)
00746   {
00747     char buf[2];
00748     buf[0]=(char)number;
00749     buf[1]=0;
00750 
00751     view->document()->insertText(view->cursorPosition(), QString(buf));
00752   }
00753   else
00754   { // do the unicode thing
00755     QChar c(number);
00756 
00757     view->document()->insertText(view->cursorPosition(), QString(&c, 1));
00758   }
00759 
00760   return true;
00761 }
00762 
00763 //END Character
00764 
00765 //BEGIN Date
00766 bool KateCommands::Date::exec (KTextEditor::View *view, const QString &cmd, QString &)
00767 {
00768   if (!cmd.startsWith(QLatin1String("date")))
00769     return false;
00770 
00771   if (QDateTime::currentDateTime().toString(cmd.mid(5, cmd.length()-5)).length() > 0)
00772     view->document()->insertText(view->cursorPosition(), QDateTime::currentDateTime().toString(cmd.mid(5, cmd.length()-5)));
00773   else
00774     view->document()->insertText(view->cursorPosition(), QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
00775 
00776   return true;
00777 }
00778 
00779 //END Date
00780 
00781 // kate: space-indent on; indent-width 2; replace-tabs on;

Kate

Skip menu "Kate"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.6.1
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal