00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
#include "katecmds.h"
00022
00023
#include "katedocument.h"
00024
#include "kateview.h"
00025
#include "kateconfig.h"
00026
#include "kateautoindent.h"
00027
00028
#include <kdebug.h>
00029
#include <klocale.h>
00030
00031
#include <qregexp.h>
00032
00033
00034
static void setDocFlag( KateDocumentConfig::ConfigFlags flag,
bool enable,
00035 KateDocument *doc )
00036 {
00037 doc->config()->setConfigFlags( flag, enable );
00038 }
00039
00040
00041
00042
00043
static bool getBoolArg(
QString s,
bool *val )
00044 {
00045
bool res(
false );
00046 s = s.
lower();
00047 res = (s ==
"on" || s ==
"1" || s ==
"true");
00048
if ( res )
00049 {
00050 *val =
true;
00051
return true;
00052 }
00053 res = (s ==
"off" || s ==
"0" || s ==
"false");
00054
if ( res )
00055 {
00056 *val =
false;
00057
return true;
00058 }
00059
return false;
00060 }
00061
00062
QStringList KateCommands::CoreCommands::cmds()
00063 {
00064
QStringList l;
00065 l <<
"indent" <<
"unindent" <<
"cleanindent"
00066 <<
"comment" <<
"uncomment"
00067 <<
"set-tab-width" <<
"set-replace-tabs" <<
"set-show-tabs"
00068 <<
"set-indent-spaces" <<
"set-indent-width" <<
"set-indent-mode" <<
"set-auto-indent"
00069 <<
"set-line-numbers" <<
"set-folding-markers" <<
"set-icon-border"
00070 <<
"set-word-wrap" <<
"set-word-wrap-column";
00071
return l;
00072 }
00073
00074
bool KateCommands::CoreCommands::exec(
Kate::View *view,
00075
const QString &_cmd,
00076
QString &errorMsg)
00077 {
00078
#define KCC_ERR(s) { errorMsg=s; return false; }
00079
00080 KateView *v = (KateView*) view;
00081
00082
if ( ! v )
00083 KCC_ERR( i18n(
"Could not access view") );
00084
00085
00086
QStringList args( QStringList::split(
QRegExp(
"\\s+"), _cmd ) );
00087
QString cmd ( args.first() );
00088 args.remove( args.first() );
00089
00090
00091
if ( cmd ==
"indent" )
00092 {
00093 v->indent();
00094
return true;
00095 }
00096
else if ( cmd ==
"unindent" )
00097 {
00098 v->unIndent();
00099
return true;
00100 }
00101
else if ( cmd ==
"cleanindent" )
00102 {
00103 v->cleanIndent();
00104
return true;
00105 }
00106
else if ( cmd ==
"comment" )
00107 {
00108 v->comment();
00109
return true;
00110 }
00111
else if ( cmd ==
"uncomment" )
00112 {
00113 v->uncomment();
00114
return true;
00115 }
00116
else if ( cmd ==
"set-indent-mode" )
00117 {
00118
bool ok(
false);
00119
int val ( args.first().toInt( &ok ) );
00120
if ( ok )
00121 {
00122
if ( val < 0 )
00123 KCC_ERR( i18n(
"Mode must be at least 0.") );
00124 v->doc()->config()->setIndentationMode( val );
00125 }
00126
else
00127 v->doc()->config()->setIndentationMode( KateAutoIndent::modeNumber( args.first() ) );
00128
return true;
00129 }
00130
00131
00132
else if ( cmd ==
"set-tab-width" ||
00133 cmd ==
"set-indent-width" ||
00134 cmd ==
"set-word-wrap-column" )
00135 {
00136
00137
if ( ! args.count() )
00138 KCC_ERR( i18n(
"Missing argument. Usage: %1 <value>").arg( cmd ) );
00139
bool ok;
00140
int val ( args.first().toInt( &ok ) );
00141
if ( !ok )
00142 KCC_ERR( i18n(
"Failed to convert argument '%1' to integer.")
00143 .arg( args.first() ) );
00144
00145
if ( cmd ==
"set-tab-width" )
00146 {
00147
if ( val < 1 )
00148 KCC_ERR( i18n(
"Width must be at least 1.") );
00149 v->setTabWidth( val );
00150 }
00151
else if ( cmd ==
"set-indent-width" )
00152 {
00153
if ( val < 1 )
00154 KCC_ERR( i18n(
"Width must be at least 1.") );
00155 v->doc()->config()->setIndentationWidth( val );
00156 }
00157
else if ( cmd ==
"set-word-wrap-column" )
00158 {
00159
if ( val < 2 )
00160 KCC_ERR( i18n(
"Column must be at least 1.") );
00161 v->doc()->setWordWrapAt( val );
00162 }
00163
return true;
00164 }
00165
00166
00167
else if ( cmd ==
"set-icon-border" ||
00168 cmd ==
"set-folding-markers" ||
00169 cmd ==
"set-line-numbers" ||
00170 cmd ==
"set-replace-tabs" ||
00171 cmd ==
"set-show-tabs" ||
00172 cmd ==
"set-indent-spaces" ||
00173 cmd ==
"set-auto-indent" ||
00174 cmd ==
"set-word-wrap" )
00175 {
00176
if ( ! args.count() )
00177 KCC_ERR( i18n(
"Usage: %1 on|off|1|0|true|false").arg( cmd ) );
00178
bool enable;
00179
if ( getBoolArg( args.first(), &enable ) )
00180 {
00181
if ( cmd ==
"set-icon-border" )
00182 v->setIconBorder( enable );
00183
else if (cmd ==
"set-folding-markers")
00184 v->setFoldingMarkersOn( enable );
00185
else if ( cmd ==
"set-line-numbers" )
00186 v->setLineNumbersOn( enable );
00187
else if ( cmd ==
"set-replace-tabs" )
00188 setDocFlag( KateDocumentConfig::cfReplaceTabs, enable, v->doc() );
00189
else if ( cmd ==
"set-show-tabs" )
00190 setDocFlag( KateDocumentConfig::cfShowTabs, enable, v->doc() );
00191
else if ( cmd ==
"set-indent-spaces" )
00192 setDocFlag( KateDocumentConfig::cfSpaceIndent, enable, v->doc() );
00193
else if ( cmd ==
"set-auto-indent" )
00194 setDocFlag( KateDocumentConfig::cfAutoIndent, enable, v->doc() );
00195
else if ( cmd ==
"set-word-wrap" )
00196 v->doc()->setWordWrap( enable );
00197
00198
return true;
00199 }
00200
else
00201 KCC_ERR( i18n(
"Bad argument '%1'. Usage: %2 on|off|1|0|true|false")
00202 .arg( args.first() ).arg( cmd ) );
00203 }
00204
00205
00206 KCC_ERR( i18n(
"Unknown command '%1'").arg(cmd) );
00207 }
00208
00209
static void replace(
QString &s,
const QString &needle,
const QString &with)
00210 {
00211
int pos=0;
00212
while (1)
00213 {
00214 pos=s.
find(needle, pos);
00215
if (pos==-1)
break;
00216 s.
replace(pos, needle.
length(), with);
00217 pos+=with.
length();
00218 }
00219
00220 }
00221
00222
static int backslashString(
const QString &haystack,
const QString &needle,
int index)
00223 {
00224
int len=haystack.
length();
00225
int searchlen=needle.
length();
00226
bool evenCount=
true;
00227
while (index<len)
00228 {
00229
if (haystack[index]==
'\\')
00230 {
00231 evenCount=!evenCount;
00232 }
00233
else
00234 {
00235
if (!evenCount)
00236 {
00237
if (haystack.
mid(index, searchlen)==needle)
00238
return index-1;
00239 }
00240 evenCount=
true;
00241 }
00242 index++;
00243
00244 }
00245
00246
return -1;
00247 }
00248
00249
00250
static void exchangeAbbrevs(
QString &str)
00251 {
00252
00253
const char *magic=
"a\x07t\t";
00254
00255
while (*magic)
00256 {
00257
int index=0;
00258
char replace=magic[1];
00259
while ((index=backslashString(str,
QChar(*magic), index))!=-1)
00260 {
00261 str.
replace(index, 2,
QChar(replace));
00262 index++;
00263 }
00264 magic++;
00265 magic++;
00266 }
00267 }
00268
00269
QString KateCommands::SedReplace::sedMagic(
QString textLine,
const QString &find,
const QString &repOld,
bool noCase,
bool repeat)
00270 {
00271
00272
QRegExp matcher(find, noCase);
00273
00274
int start=0;
00275
while (start!=-1)
00276 {
00277 start=matcher.search(textLine, start);
00278
00279
if (start==-1)
break;
00280
00281
int length=matcher.matchedLength();
00282
00283
00284
QString rep=repOld;
00285
00286
00287
QStringList backrefs=matcher.capturedTexts();
00288
int refnum=1;
00289
00290 QStringList::Iterator i = backrefs.begin();
00291 ++i;
00292
00293
for (; i!=backrefs.end(); ++i)
00294 {
00295
00296
QString number=
QString::number(refnum);
00297
00298
int index=0;
00299
while (index!=-1)
00300 {
00301 index=backslashString(rep, number, index);
00302
if (index>=0)
00303 {
00304 rep.
replace(index, 2, *i);
00305 index+=(*i).length();
00306 }
00307 }
00308
00309 refnum++;
00310 }
00311
00312
replace(rep,
"\\\\",
"\\");
00313
replace(rep,
"\\/",
"/");
00314
00315 textLine.
replace(start, length, rep);
00316
if (!repeat)
break;
00317 start+=rep.
length();
00318 }
00319
00320
00321
return textLine;
00322 }
00323
00324
static void setLineText(
Kate::View *view,
int line,
const QString &text)
00325 {
00326
if (view->getDoc()->insertLine(line, text))
00327 view->getDoc()->removeLine(line+1);
00328 }
00329
00330 bool KateCommands::SedReplace::exec (
Kate::View *view,
const QString &cmd,
QString &)
00331 {
00332
kdDebug(13010)<<
"SedReplace::execCmd()"<<
endl;
00333
00334
if (
QRegExp(
"[$%]?s /.+/.*/[ig]*").search(cmd, 0)==-1)
00335
return false;
00336
00337
bool fullFile=cmd[0]==
'%';
00338
bool noCase=cmd[cmd.length()-1]==
'i' || cmd[cmd.length()-2]==
'i';
00339
bool repeat=cmd[cmd.length()-1]==
'g' || cmd[cmd.length()-2]==
'g';
00340
bool onlySelect=cmd[0]==
'$';
00341
00342
00343
QRegExp splitter(
"^[$%]?s /((?:[^\\\\/]|\\\\.)*)/((?:[^\\\\/]|\\\\.)*)/[ig]*$");
00344
if (splitter.
search(cmd)<0)
return false;
00345
00346
QString find=splitter.
cap(1);
00347
kdDebug(13010)<<
"SedReplace: find=" << find.latin1() <<
endl;
00348
00349
QString replace=splitter.
cap(2);
00350 exchangeAbbrevs(replace);
00351
kdDebug(13010)<<
"SedReplace: replace=" << replace.latin1() <<
endl;
00352
00353
00354
if (fullFile)
00355 {
00356
int numLines=view->getDoc()->numLines();
00357
for (
int line=0; line < numLines; line++)
00358 {
00359
QString text=view->getDoc()->textLine(line);
00360 text=sedMagic(text, find, replace, noCase, repeat);
00361 setLineText(view, line, text);
00362 }
00363 }
00364
else if (onlySelect)
00365 {
00366
00367 }
00368
else
00369 {
00370
QString textLine=view->currentTextLine();
00371
int line=view->cursorLine();
00372 textLine=sedMagic(textLine, find, replace, noCase, repeat);
00373 setLineText(view, line, textLine);
00374 }
00375
return true;
00376 }
00377
00378 bool KateCommands::Character::exec (
Kate::View *view,
const QString &_cmd,
QString &)
00379 {
00380
QString cmd = _cmd;
00381
00382
00383
QRegExp num(
"^char *(0?x[0-9A-Fa-f]{1,4}|0[0-7]{1,6}|[0-9]{1,3})$");
00384
if (num.
search(cmd)==-1)
return false;
00385
00386 cmd=num.
cap(1);
00387
00388
00389
00390
unsigned short int number=0;
00391
int base=10;
00392
if (cmd[0]==
'x' || cmd.
left(2)==
"0x")
00393 {
00394 cmd.
replace(
QRegExp(
"^0?x"),
"");
00395 base=16;
00396 }
00397
else if (cmd[0]==
'0')
00398 base=8;
00399
bool ok;
00400 number=cmd.
toUShort(&ok, base);
00401
if (!ok || number==0)
return false;
00402
if (number<=255)
00403 {
00404
char buf[2];
00405 buf[0]=(
char)number;
00406 buf[1]=0;
00407 view->insertText(
QString(buf));
00408 }
00409
else
00410 {
00411
QChar c(number);
00412 view->insertText(
QString(&c, 1));
00413 }
00414
00415
return true;
00416 }
00417
00418
bool KateCommands::Goto::exec (
Kate::View *view,
const QString &cmd,
QString &)
00419 {
00420
if (cmd.
left(4) !=
"goto")
00421
return false;
00422
00423
QStringList args( QStringList::split(
QRegExp(
"\\s+"), cmd ) );
00424 args.remove( args.first() );
00425
00426 view->gotoLineNumber (args[0].toInt());
00427
00428
return true;
00429 }
00430
00431
bool KateCommands::Date::exec (
Kate::View *view,
const QString &cmd,
QString &)
00432 {
00433
if (cmd.
left(4) !=
"date")
00434
return false;
00435
00436
if (
QDateTime::currentDateTime().toString(cmd.
mid(5, cmd.
length()-5)).length() > 0)
00437 view->insertText(QDateTime::currentDateTime().toString(cmd.
mid(5, cmd.
length()-5)));
00438
else
00439 view->insertText(QDateTime::currentDateTime().toString(
"yyyy-MM-dd hh:mm:ss"));
00440
00441
return true;
00442 }
00443
00444