23 #include "katedocument.h"
25 #include "kateconfig.h"
26 #include "kateautoindent.h"
27 #include "katetextline.h"
28 #include "katefactory.h"
29 #include "katejscript.h"
30 #include "katerenderer.h"
32 #include "../interfaces/katecmd.h"
37 #include <kshellcompletion.h>
44 static void setDocFlag( KateDocumentConfig::ConfigFlags flag,
bool enable,
47 doc->config()->setConfigFlags( flag, enable );
53 static bool getBoolArg( TQString s,
bool *val )
57 res = (s ==
"on" || s ==
"1" || s ==
"true");
63 res = (s ==
"off" || s ==
"0" || s ==
"false");
75 l <<
"indent" <<
"unindent" <<
"cleanindent"
76 <<
"comment" <<
"uncomment" <<
"goto" <<
"kill-line"
77 <<
"set-tab-width" <<
"set-replace-tabs" <<
"set-show-tabs"
78 <<
"set-remove-trailing-space"
79 <<
"set-indent-spaces" <<
"set-indent-width" <<
"set-mixed-indent"
80 <<
"set-indent-mode" <<
"set-auto-indent"
81 <<
"set-line-numbers" <<
"set-folding-markers" <<
"set-icon-border"
83 <<
"set-word-wrap" <<
"set-word-wrap-column"
84 <<
"set-replace-tabs-save" <<
"set-remove-trailing-space-save"
85 <<
"set-highlight" <<
"run-myself" <<
"set-show-indent";
93 #define KCC_ERR(s) { errorMsg=s; return false; }
95 KateView *v = (KateView*) view;
98 KCC_ERR( i18n(
"Could not access view") );
101 TQStringList args( TQStringList::split( TQRegExp(
"\\s+"), _cmd ) );
102 TQString cmd ( args.first() );
103 args.remove( args.first() );
106 if ( cmd ==
"indent" )
111 else if ( cmd ==
"run-myself" )
114 return KateFactory::self()->jscript()->execute(v, v->doc()->text(), errorMsg);
119 else if ( cmd ==
"unindent" )
124 else if ( cmd ==
"cleanindent" )
129 else if ( cmd ==
"comment" )
134 else if ( cmd ==
"uncomment" )
139 else if ( cmd ==
"kill-line" )
144 else if ( cmd ==
"set-indent-mode" )
147 int val ( args.first().toInt( &ok ) );
151 KCC_ERR( i18n(
"Mode must be at least 0.") );
152 v->doc()->config()->setIndentationMode( val );
158 else if ( cmd ==
"set-highlight" )
160 TQString val = TQString(_cmd.section(
' ', 1 )).lower();
161 for ( uint i=0; i < v->doc()->hlModeCount(); i++ )
163 if ( v->doc()->hlModeName( i ).lower() == val )
165 v->doc()->setHlMode( i );
169 KCC_ERR( i18n(
"No such highlight '%1'").arg( args.first() ) );
173 else if ( cmd ==
"set-tab-width" ||
174 cmd ==
"set-indent-width" ||
175 cmd ==
"set-word-wrap-column" ||
179 if ( ! args.count() )
180 KCC_ERR( i18n(
"Missing argument. Usage: %1 <value>").arg( cmd ) );
182 int val ( args.first().toInt( &ok ) );
184 KCC_ERR( i18n(
"Failed to convert argument '%1' to integer.")
185 .arg( args.first() ) );
187 if ( cmd ==
"set-tab-width" )
190 KCC_ERR( i18n(
"Width must be at least 1.") );
191 v->setTabWidth( val );
193 else if ( cmd ==
"set-indent-width" )
196 KCC_ERR( i18n(
"Width must be at least 1.") );
197 v->doc()->config()->setIndentationWidth( val );
199 else if ( cmd ==
"set-word-wrap-column" )
202 KCC_ERR( i18n(
"Column must be at least 1.") );
203 v->doc()->setWordWrapAt( val );
205 else if ( cmd ==
"goto" )
208 KCC_ERR( i18n(
"Line must be at least 1") );
209 if ( (uint)val > v->doc()->numLines() )
210 KCC_ERR( i18n(
"There is not that many lines in this document") );
211 v->gotoLineNumber( val - 1 );
217 else if ( cmd ==
"set-icon-border" ||
218 cmd ==
"set-folding-markers" ||
219 cmd ==
"set-line-numbers" ||
220 cmd ==
"set-replace-tabs" ||
221 cmd ==
"set-remove-trailing-space" ||
222 cmd ==
"set-show-tabs" ||
223 cmd ==
"set-indent-spaces" ||
224 cmd ==
"set-mixed-indent" ||
225 cmd ==
"set-word-wrap" ||
226 cmd ==
"set-wrap-cursor" ||
227 cmd ==
"set-replace-tabs-save" ||
228 cmd ==
"set-remove-trailing-space-save" ||
229 cmd ==
"set-show-indent" )
231 if ( ! args.count() )
232 KCC_ERR( i18n(
"Usage: %1 on|off|1|0|true|false").arg( cmd ) );
234 if ( getBoolArg( args.first(), &enable ) )
236 if ( cmd ==
"set-icon-border" )
237 v->setIconBorder( enable );
238 else if (cmd ==
"set-folding-markers")
239 v->setFoldingMarkersOn( enable );
240 else if ( cmd ==
"set-line-numbers" )
241 v->setLineNumbersOn( enable );
242 else if ( cmd ==
"set-show-indent" )
243 v->renderer()->setShowIndentLines( enable );
244 else if ( cmd ==
"set-replace-tabs" )
245 setDocFlag( KateDocumentConfig::cfReplaceTabsDyn, enable, v->doc() );
246 else if ( cmd ==
"set-remove-trailing-space" )
247 setDocFlag( KateDocumentConfig::cfRemoveTrailingDyn, enable, v->doc() );
248 else if ( cmd ==
"set-show-tabs" )
249 setDocFlag( KateDocumentConfig::cfShowTabs, enable, v->doc() );
250 else if ( cmd ==
"set-indent-spaces" )
251 setDocFlag( KateDocumentConfig::cfSpaceIndent, enable, v->doc() );
252 else if ( cmd ==
"set-mixed-indent" )
256 setDocFlag( KateDocumentConfig::cfMixedIndent, enable, v->doc() );
259 setDocFlag( KateDocumentConfig::cfSpaceIndent, enable, v->doc() );
260 if ( ! v->doc()->config()->indentationWidth() )
261 v->doc()->config()->setIndentationWidth( v->tabWidth()/2 );
264 else if ( cmd ==
"set-word-wrap" )
265 v->doc()->setWordWrap( enable );
266 else if ( cmd ==
"set-remove-trailing-space-save" )
267 setDocFlag( KateDocumentConfig::cfRemoveSpaces, enable, v->doc() );
268 else if ( cmd ==
"set-wrap-cursor" )
269 setDocFlag( KateDocumentConfig::cfWrapCursor, enable, v->doc() );
274 KCC_ERR( i18n(
"Bad argument '%1'. Usage: %2 on|off|1|0|true|false")
275 .arg( args.first() ).arg( cmd ) );
279 KCC_ERR( i18n(
"Unknown command '%1'").arg(cmd) );
284 if ( cmd ==
"set-highlight" )
286 KateView *v = (KateView*)view;
288 for ( uint i = 0; i < v->doc()->hlModeCount(); i++ )
289 l << v->doc()->hlModeName( i );
301 static void replace(TQString &s,
const TQString &needle,
const TQString &with)
306 pos=s.find(needle, pos);
308 s.replace(pos, needle.length(), with);
314 static int backslashString(
const TQString &haystack,
const TQString &needle,
int index)
316 int len=haystack.length();
317 int searchlen=needle.length();
321 if (haystack[index]==
'\\')
323 evenCount=!evenCount;
329 if (haystack.mid(index, searchlen)==needle)
342 static void exchangeAbbrevs(TQString &str)
345 const char *magic=
"a\x07t\tn\n";
351 while ((index=backslashString(str, TQChar(*magic), index))!=-1)
353 str.replace(index, 2, TQChar(replace));
361 int KateCommands::SedReplace::sedMagic( KateDocument *doc,
int &line,
362 const TQString &find,
const TQString &repOld,
const TQString &delim,
363 bool noCase,
bool repeat,
364 uint startcol,
int endcol )
367 if ( ! ln || ! ln->
length() )
return 0;
379 TQStringList patterns = TQStringList::split( TQRegExp(
"(^\\\\n|(?![^\\\\])\\\\n)"), find,
true );
381 if ( patterns.count() > 1 )
383 for ( uint i = 0; i < patterns.count(); i++ )
385 if ( i < patterns.count() - 1 )
386 patterns[i].append(
"$");
388 patterns[i].prepend(
"^");
390 kdDebug(13025)<<
"patterns["<<i<<
"] ="<<patterns[i]<<
endl;
394 TQRegExp matcher(patterns[0], noCase);
399 while ( ln->
searchText( startcol, matcher, &startcol, &len ) )
402 if ( endcol >= 0 && startcol + len > (uint)endcol )
411 TQStringList backrefs=matcher.capturedTexts();
414 TQStringList::Iterator i = backrefs.begin();
417 for (; i!=backrefs.end(); ++i)
420 TQString number=TQString::number(refnum);
425 index=backslashString(rep, number, index);
428 rep.replace(index, 2, *i);
429 index+=(*i).length();
437 replace(rep,
"\\" + delim, delim);
439 doc->removeText( line, startcol, line, startcol + len );
440 doc->insertText( line, startcol, rep );
445 int lns = rep.contains(
'\n');
450 if ( doc->lineLength( line ) > 0 && ( endcol < 0 || (uint)endcol >= startcol + len ) )
453 endcol -= (startcol + len);
454 uint sc = rep.length() - rep.findRev(
'\n') - 1;
455 matches += sedMagic( doc, line, find, repOld, delim, noCase, repeat, sc, endcol );
460 startcol+=rep.length();
464 if ( ! ll || startcol > ll )
473 kdDebug(13025)<<
"SedReplace::execCmd( "<<cmd<<
" )"<<
endl;
475 TQRegExp delim(
"^[$%]?s\\s*([^\\w\\s])");
476 if ( delim.search( cmd ) < 0 )
return false;
478 bool fullFile=cmd[0]==
'%';
479 bool noCase=cmd[cmd.length()-1]==
'i' || cmd[cmd.length()-2]==
'i';
480 bool repeat=cmd[cmd.length()-1]==
'g' || cmd[cmd.length()-2]==
'g';
481 bool onlySelect=cmd[0]==
'$';
483 TQString d = delim.cap(1);
484 kdDebug(13025)<<
"SedReplace: delimiter is '"<<d<<
"'"<<
endl;
486 TQRegExp splitter( TQString(
"^[$%]?s\\s*") + d +
"((?:[^\\\\\\" + d +
"]|\\\\.)*)\\" + d +
"((?:[^\\\\\\" + d +
"]|\\\\.)*)\\" + d +
"[ig]{0,2}$" );
487 if (splitter.search(cmd)<0)
return false;
489 TQString find=splitter.cap(1);
490 kdDebug(13025)<<
"SedReplace: find=" << find.latin1() <<
endl;
492 TQString replace=splitter.cap(2);
493 exchangeAbbrevs(replace);
494 kdDebug(13025)<<
"SedReplace: replace=" << replace.latin1() <<
endl;
498 msg = i18n(
"Sorry, but Kate is not able to replace newlines, yet");
502 KateDocument *doc = ((KateView*)view)->doc();
503 if ( ! doc )
return false;
511 uint numLines=doc->numLines();
512 for (
int line=0; (uint)line < numLines; line++)
514 res += sedMagic( doc, line, find, replace, d, !noCase, repeat );
515 if ( ! repeat && res )
break;
520 int startline = doc->selStartLine();
521 uint startcol = doc->selStartCol();
524 if ( startline == doc->selEndLine() )
525 endcol = doc->selEndCol();
527 res += sedMagic( doc, startline, find, replace, d, !noCase, repeat, startcol, endcol );
532 }
while ( (
int)startline <= doc->selEndLine() );
536 int line=view->cursorLine();
537 res += sedMagic(doc, line, find, replace, d, !noCase, repeat);
540 msg = i18n(
"1 replacement done",
"%n replacements done",res );
554 TQRegExp num(
"^char *(0?x[0-9A-Fa-f]{1,4}|0[0-7]{1,6}|[0-9]{1,3})$");
555 if (num.search(cmd)==-1)
return false;
561 unsigned short int number=0;
563 if (cmd[0]==
'x' || cmd.left(2)==
"0x")
565 cmd.replace(TQRegExp(
"^0?x"),
"");
568 else if (cmd[0]==
'0')
571 number=cmd.toUShort(&ok, base);
572 if (!ok || number==0)
return false;
593 if (cmd.left(4) !=
"date")
596 if (TQDateTime::currentDateTime().toString(cmd.mid(5, cmd.length()-5)).length() > 0)
597 view->
insertText(TQDateTime::currentDateTime().toString(cmd.mid(5, cmd.length()-5)));
599 view->
insertText(TQDateTime::currentDateTime().toString(
"yyyy-MM-dd hh:mm:ss"));
virtual uint modeNumber() const
Mode index of this mode.
A TDECompletion object that completes last ?unquoted? word in the string passed.
bool exec(class Kate::View *view, const TQString &cmd, TQString &errorMsg)
execute command
TQStringList cmds()
supported commands as prefixes
bool exec(class Kate::View *view, const TQString &cmd, TQString &errorMsg)
execute command
TDECompletion * completionObject(const TQString &cmd, Kate::View *view)
override completionObject from interfaces/document.h .
bool exec(class Kate::View *view, const TQString &cmd, TQString &errorMsg)
execute command
bool exec(class Kate::View *view, const TQString &cmd, TQString &errorMsg)
execute command
The KateTextLine represents a line of text.
uint length() const
Returns the length.
bool searchText(uint startCol, const TQString &text, uint *foundAtCol, uint *matchLen, bool casesensitive=true, bool backwards=false)
search given string
The Kate::View text editor interface.
virtual void insertText(const TQString &mark)
Insert text at the current cursor position.
virtual void setItems(const TQStringList &list)
virtual void setIgnoreCase(bool ignoreCase)
bool contains(const KKey &key) const
kndbgstream & endl(kndbgstream &s)
kdbgstream kdDebug(int area=0)
const TDEShortcut & replace()