• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • kate
 

kate

  • kate
  • part
katecmds.cpp
1/* This file is part of the KDE libraries
2 Copyright (C) 2003 - 2005 Anders Lund <anders@alweb.dk>
3 Copyright (C) 2001-2004 Christoph Cullmann <cullmann@kde.org>
4 Copyright (C) 2001 Charles Samuels <charles@kde.org>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License version 2 as published by the Free Software Foundation.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public License
16 along with this library; see the file COPYING.LIB. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
19*/
20
21#include "katecmds.h"
22
23#include "katedocument.h"
24#include "kateview.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"
31
32#include "../interfaces/katecmd.h"
33
34#include <kdebug.h>
35#include <tdelocale.h>
36#include <kurl.h>
37#include <kshellcompletion.h>
38
39#include <tqregexp.h>
40
41
42//BEGIN CoreCommands
43// syncs a config flag in the document with a boolean value
44static void setDocFlag( KateDocumentConfig::ConfigFlags flag, bool enable,
45 KateDocument *doc )
46{
47 doc->config()->setConfigFlags( flag, enable );
48}
49
50// this returns wheather the string s could be converted to
51// a bool value, one of on|off|1|0|true|false. the argument val is
52// set to the extracted value in case of success
53static bool getBoolArg( TQString s, bool *val )
54{
55 bool res( false );
56 s = s.lower();
57 res = (s == "on" || s == "1" || s == "true");
58 if ( res )
59 {
60 *val = true;
61 return true;
62 }
63 res = (s == "off" || s == "0" || s == "false");
64 if ( res )
65 {
66 *val = false;
67 return true;
68 }
69 return false;
70}
71
72TQStringList KateCommands::CoreCommands::cmds()
73{
74 TQStringList l;
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"
82 << "set-wrap-cursor"
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";
86 return l;
87}
88
89bool KateCommands::CoreCommands::exec(Kate::View *view,
90 const TQString &_cmd,
91 TQString &errorMsg)
92{
93#define KCC_ERR(s) { errorMsg=s; return false; }
94 // cast it hardcore, we know that it is really a kateview :)
95 KateView *v = (KateView*) view;
96
97 if ( ! v )
98 KCC_ERR( i18n("Could not access view") );
99
100 //create a list of args
101 TQStringList args( TQStringList::split( TQRegExp("\\s+"), _cmd ) );
102 TQString cmd ( args.first() );
103 args.remove( args.first() );
104
105 // ALL commands that takes no arguments.
106 if ( cmd == "indent" )
107 {
108 v->indent();
109 return true;
110 }
111 else if ( cmd == "run-myself" )
112 {
113#ifndef TQ_WS_WIN //todo
114 return KateFactory::self()->jscript()->execute(v, v->doc()->text(), errorMsg);
115#else
116 return 0;
117#endif
118 }
119 else if ( cmd == "unindent" )
120 {
121 v->unIndent();
122 return true;
123 }
124 else if ( cmd == "cleanindent" )
125 {
126 v->cleanIndent();
127 return true;
128 }
129 else if ( cmd == "comment" )
130 {
131 v->comment();
132 return true;
133 }
134 else if ( cmd == "uncomment" )
135 {
136 v->uncomment();
137 return true;
138 }
139 else if ( cmd == "kill-line" )
140 {
141 v->killLine();
142 return true;
143 }
144 else if ( cmd == "set-indent-mode" )
145 {
146 bool ok(false);
147 int val ( args.first().toInt( &ok ) );
148 if ( ok )
149 {
150 if ( val < 0 )
151 KCC_ERR( i18n("Mode must be at least 0.") );
152 v->doc()->config()->setIndentationMode( val );
153 }
154 else
155 v->doc()->config()->setIndentationMode( KateAutoIndent::modeNumber( args.first() ) );
156 return true;
157 }
158 else if ( cmd == "set-highlight" )
159 {
160 TQString val = TQString(_cmd.section( ' ', 1 )).lower();
161 for ( uint i=0; i < v->doc()->hlModeCount(); i++ )
162 {
163 if ( v->doc()->hlModeName( i ).lower() == val )
164 {
165 v->doc()->setHlMode( i );
166 return true;
167 }
168 }
169 KCC_ERR( i18n("No such highlight '%1'").arg( args.first() ) );
170 }
171
172 // ALL commands that takes exactly one integer argument.
173 else if ( cmd == "set-tab-width" ||
174 cmd == "set-indent-width" ||
175 cmd == "set-word-wrap-column" ||
176 cmd == "goto" )
177 {
178 // find a integer value > 0
179 if ( ! args.count() )
180 KCC_ERR( i18n("Missing argument. Usage: %1 <value>").arg( cmd ) );
181 bool ok;
182 int val ( args.first().toInt( &ok ) );
183 if ( !ok )
184 KCC_ERR( i18n("Failed to convert argument '%1' to integer.")
185 .arg( args.first() ) );
186
187 if ( cmd == "set-tab-width" )
188 {
189 if ( val < 1 )
190 KCC_ERR( i18n("Width must be at least 1.") );
191 v->setTabWidth( val );
192 }
193 else if ( cmd == "set-indent-width" )
194 {
195 if ( val < 1 )
196 KCC_ERR( i18n("Width must be at least 1.") );
197 v->doc()->config()->setIndentationWidth( val );
198 }
199 else if ( cmd == "set-word-wrap-column" )
200 {
201 if ( val < 2 )
202 KCC_ERR( i18n("Column must be at least 1.") );
203 v->doc()->setWordWrapAt( val );
204 }
205 else if ( cmd == "goto" )
206 {
207 if ( val < 1 )
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 );
212 }
213 return true;
214 }
215
216 // ALL commands that takes 1 boolean argument.
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" )
230 {
231 if ( ! args.count() )
232 KCC_ERR( i18n("Usage: %1 on|off|1|0|true|false").arg( cmd ) );
233 bool enable;
234 if ( getBoolArg( args.first(), &enable ) )
235 {
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" )
253 {
254 // this is special, in that everything is set up -- space-indent is enabled,
255 // and a indent-width is set if it is 0 (to tabwidth/2)
256 setDocFlag( KateDocumentConfig::cfMixedIndent, enable, v->doc() );
257 if ( enable )
258 {
259 setDocFlag( KateDocumentConfig::cfSpaceIndent, enable, v->doc() );
260 if ( ! v->doc()->config()->indentationWidth() )
261 v->doc()->config()->setIndentationWidth( v->tabWidth()/2 );
262 }
263 }
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() );
270
271 return true;
272 }
273 else
274 KCC_ERR( i18n("Bad argument '%1'. Usage: %2 on|off|1|0|true|false")
275 .arg( args.first() ).arg( cmd ) );
276 }
277
278 // unlikely..
279 KCC_ERR( i18n("Unknown command '%1'").arg(cmd) );
280}
281
282TDECompletion *KateCommands::CoreCommands::completionObject( const TQString &cmd, Kate::View *view )
283{
284 if ( cmd == "set-highlight" )
285 {
286 KateView *v = (KateView*)view;
287 TQStringList l;
288 for ( uint i = 0; i < v->doc()->hlModeCount(); i++ )
289 l << v->doc()->hlModeName( i );
290
291 KateCmdShellCompletion *co = new KateCmdShellCompletion();
292 co->setItems( l );
293 co->setIgnoreCase( true );
294 return co;
295 }
296 return 0L;
297}
298//END CoreCommands
299
300//BEGIN SedReplace
301static void replace(TQString &s, const TQString &needle, const TQString &with)
302{
303 int pos=0;
304 while (1)
305 {
306 pos=s.find(needle, pos);
307 if (pos==-1) break;
308 s.replace(pos, needle.length(), with);
309 pos+=with.length();
310 }
311
312}
313
314static int backslashString(const TQString &haystack, const TQString &needle, int index)
315{
316 int len=haystack.length();
317 int searchlen=needle.length();
318 bool evenCount=true;
319 while (index<len)
320 {
321 if (haystack[index]=='\\')
322 {
323 evenCount=!evenCount;
324 }
325 else
326 { // isn't a slash
327 if (!evenCount)
328 {
329 if (haystack.mid(index, searchlen)==needle)
330 return index-1;
331 }
332 evenCount=true;
333 }
334 index++;
335
336 }
337
338 return -1;
339}
340
341// exchange "\t" for the actual tab character, for example
342static void exchangeAbbrevs(TQString &str)
343{
344 // the format is (findreplace)*[nullzero]
345 const char *magic="a\x07t\tn\n";
346
347 while (*magic)
348 {
349 int index=0;
350 char replace=magic[1];
351 while ((index=backslashString(str, TQChar(*magic), index))!=-1)
352 {
353 str.replace(index, 2, TQChar(replace));
354 index++;
355 }
356 magic++;
357 magic++;
358 }
359}
360
361int 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 )
365{
366 KateTextLine *ln = doc->kateTextLine( line );
367 if ( ! ln || ! ln->length() ) return 0;
368
369 // HANDLING "\n"s in PATTERN
370 // * Create a list of patterns, splitting PATTERN on (unescaped) "\n"
371 // * insert $s and ^s to match line ends/beginnings
372 // * When matching patterhs after the first one, replace \N with the captured
373 // text.
374 // * If all patterns in the list match sequentiel lines, there is a match, so
375 // * remove line/start to line + patterns.count()-1/patterns.last.length
376 // * handle capatures by putting them in one list.
377 // * the existing insertion is fine, including the line calculation.
378
379 TQStringList patterns = TQStringList::split( TQRegExp("(^\\\\n|(?![^\\\\])\\\\n)"), find, true );
380
381 if ( patterns.count() > 1 )
382 {
383 for ( uint i = 0; i < patterns.count(); i++ )
384 {
385 if ( i < patterns.count() - 1 )
386 patterns[i].append("$");
387 if ( i )
388 patterns[i].prepend("^");
389
390 kdDebug(13025)<<"patterns["<<i<<"] ="<<patterns[i]<<endl;
391 }
392 }
393
394 TQRegExp matcher(patterns[0], noCase);
395
396 uint len;
397 int matches = 0;
398
399 while ( ln->searchText( startcol, matcher, &startcol, &len ) )
400 {
401
402 if ( endcol >= 0 && startcol + len > (uint)endcol )
403 break;
404
405 matches++;
406
407
408 TQString rep=repOld;
409
410 // now set the backreferences in the replacement
411 TQStringList backrefs=matcher.capturedTexts();
412 int refnum=1;
413
414 TQStringList::Iterator i = backrefs.begin();
415 ++i;
416
417 for (; i!=backrefs.end(); ++i)
418 {
419 // I need to match "\\" or "", but not "\"
420 TQString number=TQString::number(refnum);
421
422 int index=0;
423 while (index!=-1)
424 {
425 index=backslashString(rep, number, index);
426 if (index>=0)
427 {
428 rep.replace(index, 2, *i);
429 index+=(*i).length();
430 }
431 }
432
433 refnum++;
434 }
435
436 replace(rep, "\\\\", "\\");
437 replace(rep, "\\" + delim, delim);
438
439 doc->removeText( line, startcol, line, startcol + len );
440 doc->insertText( line, startcol, rep );
441
442 // TODO if replace contains \n,
443 // change the line number and
444 // check for text that needs be searched behind the last inserted newline.
445 int lns = rep.contains('\n');
446 if ( lns )
447 {
448 line += lns;
449
450 if ( doc->lineLength( line ) > 0 && ( endcol < 0 || (uint)endcol >= startcol + len ) )
451 {
452 // if ( 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 );
456 }
457 }
458
459 if (!repeat) break;
460 startcol+=rep.length();
461
462 // sanity check -- avoid infinite loops eg with %s,.*,,g ;)
463 uint ll = ln->length();
464 if ( ! ll || startcol > ll )
465 break;
466 }
467
468 return matches;
469}
470
471bool KateCommands::SedReplace::exec (Kate::View *view, const TQString &cmd, TQString &msg)
472{
473 kdDebug(13025)<<"SedReplace::execCmd( "<<cmd<<" )"<<endl;
474
475 TQRegExp delim("^[$%]?s\\s*([^\\w\\s])");
476 if ( delim.search( cmd ) < 0 ) return false;
477
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]=='$';
482
483 TQString d = delim.cap(1);
484 kdDebug(13025)<<"SedReplace: delimiter is '"<<d<<"'"<<endl;
485
486 TQRegExp splitter( TQString("^[$%]?s\\s*") + d + "((?:[^\\\\\\" + d + "]|\\\\.)*)\\" + d +"((?:[^\\\\\\" + d + "]|\\\\.)*)\\" + d + "[ig]{0,2}$" );
487 if (splitter.search(cmd)<0) return false;
488
489 TQString find=splitter.cap(1);
490 kdDebug(13025)<< "SedReplace: find=" << find.latin1() <<endl;
491
492 TQString replace=splitter.cap(2);
493 exchangeAbbrevs(replace);
494 kdDebug(13025)<< "SedReplace: replace=" << replace.latin1() <<endl;
495
496 if ( find.contains("\\n") )
497 {
498 msg = i18n("Sorry, but Kate is not able to replace newlines, yet");
499 return false;
500 }
501
502 KateDocument *doc = ((KateView*)view)->doc();
503 if ( ! doc ) return false;
504
505 doc->editStart();
506
507 int res = 0;
508
509 if (fullFile)
510 {
511 uint numLines=doc->numLines();
512 for (int line=0; (uint)line < numLines; line++)
513 {
514 res += sedMagic( doc, line, find, replace, d, !noCase, repeat );
515 if ( ! repeat && res ) break;
516 }
517 }
518 else if (onlySelect)
519 {
520 int startline = doc->selStartLine();
521 uint startcol = doc->selStartCol();
522 int endcol = -1;
523 do {
524 if ( startline == doc->selEndLine() )
525 endcol = doc->selEndCol();
526
527 res += sedMagic( doc, startline, find, replace, d, !noCase, repeat, startcol, endcol );
528
529 /*if ( startcol )*/ startcol = 0;
530
531 startline++;
532 } while ( (int)startline <= doc->selEndLine() );
533 }
534 else // just this line
535 {
536 int line=view->cursorLine();
537 res += sedMagic(doc, line, find, replace, d, !noCase, repeat);
538 }
539
540 msg = i18n("1 replacement done", "%n replacements done",res );
541
542 doc->editEnd();
543
544 return true;
545}
546//END SedReplace
547
548//BEGIN Character
549bool KateCommands::Character::exec (Kate::View *view, const TQString &_cmd, TQString &)
550{
551 TQString cmd = _cmd;
552
553 // hex, octal, base 9+1
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;
556
557 cmd=num.cap(1);
558
559 // identify the base
560
561 unsigned short int number=0;
562 int base=10;
563 if (cmd[0]=='x' || cmd.left(2)=="0x")
564 {
565 cmd.replace(TQRegExp("^0?x"), "");
566 base=16;
567 }
568 else if (cmd[0]=='0')
569 base=8;
570 bool ok;
571 number=cmd.toUShort(&ok, base);
572 if (!ok || number==0) return false;
573 if (number<=255)
574 {
575 char buf[2];
576 buf[0]=(char)number;
577 buf[1]=0;
578 view->insertText(TQString(buf));
579 }
580 else
581 { // do the unicode thing
582 TQChar c(number);
583 view->insertText(TQString(&c, 1));
584 }
585
586 return true;
587}
588//END Character
589
590//BEGIN Date
591bool KateCommands::Date::exec (Kate::View *view, const TQString &cmd, TQString &)
592{
593 if (cmd.left(4) != "date")
594 return false;
595
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)));
598 else
599 view->insertText(TQDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss"));
600
601 return true;
602}
603//END Date
KateAutoIndent::modeNumber
virtual uint modeNumber() const
Mode index of this mode.
Definition: kateautoindent.h:185
KateCmdShellCompletion
A TDECompletion object that completes last ?unquoted? word in the string passed.
Definition: katecmd.h:62
KateCommands::Character::exec
bool exec(class Kate::View *view, const TQString &cmd, TQString &errorMsg)
execute command
Definition: katecmds.cpp:549
KateCommands::CoreCommands::cmds
TQStringList cmds()
supported commands as prefixes
Definition: katecmds.cpp:72
KateCommands::CoreCommands::exec
bool exec(class Kate::View *view, const TQString &cmd, TQString &errorMsg)
execute command
Definition: katecmds.cpp:89
KateCommands::CoreCommands::completionObject
TDECompletion * completionObject(const TQString &cmd, Kate::View *view)
override completionObject from interfaces/document.h .
Definition: katecmds.cpp:282
KateCommands::Date::exec
bool exec(class Kate::View *view, const TQString &cmd, TQString &errorMsg)
execute command
Definition: katecmds.cpp:591
KateCommands::SedReplace::exec
bool exec(class Kate::View *view, const TQString &cmd, TQString &errorMsg)
execute command
Definition: katecmds.cpp:471
KateTextLine
The KateTextLine represents a line of text.
Definition: katetextline.h:42
KateTextLine::length
uint length() const
Returns the length.
Definition: katetextline.h:97
KateTextLine::searchText
bool searchText(uint startCol, const TQString &text, uint *foundAtCol, uint *matchLen, bool casesensitive=true, bool backwards=false)
search given string
Definition: katetextline.cpp:273
Kate::View
The Kate::View text editor interface.
Definition: view.h:45
Kate::View::insertText
virtual void insertText(const TQString &mark)
Insert text at the current cursor position.
Definition: view.h:86
TDECompletion
TDECompletion::setItems
virtual void setItems(const TQStringList &list)
TDECompletion::setIgnoreCase
virtual void setIgnoreCase(bool ignoreCase)
TDEShortcut::contains
bool contains(const KKey &key) const
endl
kndbgstream & endl(kndbgstream &s)
kdDebug
kdbgstream kdDebug(int area=0)
TDEStdAccel::replace
const TDEShortcut & replace()
tdelocale.h

kate

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

kate

Skip menu "kate"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kate by doxygen 1.9.4
This website is maintained by Timothy Pearson.