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

kate

  • kate
  • part
katejscript.cpp
1/* This file is part of the KDE libraries
2 Copyright (C) 2005 Christoph Cullmann <cullmann@kde.org>
3 Copyright (C) 2005 Joseph Wenninger <jowenn@kde.org>
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License version 2 as published by the Free Software Foundation.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19
20#include "katejscript.h"
21
22#include "katedocument.h"
23#include "kateview.h"
24#include "katefactory.h"
25#include "kateconfig.h"
26#include "kateautoindent.h"
27#include "katehighlight.h"
28#include "katetextline.h"
29
30#include "kateindentscriptabstracts.h"
31
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <unistd.h>
35
36#include <kdebug.h>
37#include <tdestandarddirs.h>
38#include <tdelocale.h>
39#include <tdemessagebox.h>
40#include <tdeconfig.h>
41
42#include <kjs/function_object.h>
43#include <kjs/interpreter.h>
44#include <kjs/lookup.h>
45
46#include <tqfile.h>
47#include <tqfileinfo.h>
48#include <tqpopupmenu.h>
49#include <tqregexp.h>
50#include <tqtextstream.h>
51
52
53namespace KJS {
54
55// taken from tdehtml
56// therefor thx to:
57// Copyright (C) 1999-2003 Harri Porten (porten@kde.org)
58// Copyright (C) 2001-2003 David Faure (faure@kde.org)
59// Copyright (C) 2003 Apple Computer, Inc.
60
61UString::UString(const TQString &d)
62{
63 unsigned int len = d.length();
64 UChar *dat = new UChar[len];
65 memcpy(dat, d.unicode(), len * sizeof(UChar));
66 rep = UString::Rep::create(dat, len);
67}
68
69TQString UString::qstring() const
70{
71 return TQString((TQChar*) data(), size());
72}
73
74TQConstString UString::qconststring() const
75{
76 return TQConstString((TQChar*) data(), size());
77}
78
79//BEGIN global methods
80class KateJSGlobalFunctions : public ObjectImp
81{
82 public:
83 KateJSGlobalFunctions(int i, int length);
84 virtual bool implementsCall() const { return true; }
85 virtual Value call(ExecState *exec, Object &thisObj, const List &args);
86
87 enum {
88 Debug
89 };
90
91 private:
92 int id;
93};
94KateJSGlobalFunctions::KateJSGlobalFunctions(int i, int length) : ObjectImp(), id(i)
95{
96 putDirect(lengthPropertyName,length,DontDelete|ReadOnly|DontEnum);
97}
98Value KateJSGlobalFunctions::call(ExecState *exec, Object &/*thisObj*/, const List &args)
99{
100 switch (id) {
101 case Debug:
102 tqDebug("Kate (KJS Scripting): %s", args[0].toString(exec).ascii());
103 return Undefined();
104 default:
105 break;
106 }
107
108 return Undefined();
109}
110//END global methods
111
112} // namespace KJS
113
114//BEGIN JS API STUFF
115
116class KateJSGlobal : public KJS::ObjectImp {
117public:
118 virtual KJS::UString className() const { return "global"; }
119};
120
121class KateJSDocument : public KJS::ObjectImp
122{
123 public:
124 KateJSDocument (KJS::ExecState *exec, KateDocument *_doc);
125
126 KJS::Value get( KJS::ExecState *exec, const KJS::Identifier &propertyName) const;
127
128 KJS::Value getValueProperty(KJS::ExecState *exec, int token) const;
129
130 void put(KJS::ExecState *exec, const KJS::Identifier &propertyName, const KJS::Value& value, int attr = KJS::None);
131
132 void putValueProperty(KJS::ExecState *exec, int token, const KJS::Value& value, int attr);
133
134 const KJS::ClassInfo* classInfo() const { return &info; }
135
136 enum { FullText,
137 Text,
138 TextLine,
139 Lines,
140 Length,
141 LineLength,
142 SetText,
143 Clear,
144 InsertText,
145 RemoveText,
146 InsertLine,
147 RemoveLine,
148 EditBegin,
149 EditEnd,
150 IndentWidth,
151 IndentMode,
152 SpaceIndent,
153 MixedIndent,
154 HighlightMode,
155 IsInWord,
156 CanBreakAt,
157 CanComment,
158 CommentMarker,
159 CommentStart,
160 CommentEnd,
161 Attribute
162 };
163
164 public:
165 KateDocument *doc;
166
167 static const KJS::ClassInfo info;
168};
169
170class KateJSView : public KJS::ObjectImp
171{
172 public:
173 KateJSView (KJS::ExecState *exec, KateView *_view);
174
175 KJS::Value get( KJS::ExecState *exec, const KJS::Identifier &propertyName) const;
176
177 KJS::Value getValueProperty(KJS::ExecState *exec, int token) const;
178
179 void put(KJS::ExecState *exec, const KJS::Identifier &propertyName, const KJS::Value& value, int attr = KJS::None);
180
181 void putValueProperty(KJS::ExecState *exec, int token, const KJS::Value& value, int attr);
182
183 const KJS::ClassInfo* classInfo() const { return &info; }
184
185 enum { CursorLine,
186 CursorColumn,
187 CursorColumnReal,
188 SetCursorPosition,
189 SetCursorPositionReal,
190 Selection,
191 HasSelection,
192 SetSelection,
193 RemoveSelectedText,
194 SelectAll,
195 ClearSelection,
196 SelStartLine,
197 SelStartCol,
198 SelEndLine,
199 SelEndCol
200 };
201
202 public:
203 KateView *view;
204
205 static const KJS::ClassInfo info;
206};
207
208class KateJSIndenter : public KJS::ObjectImp
209{
210 public:
211 KateJSIndenter (KJS::ExecState *exec);
212 /*
213 KJS::Value get( KJS::ExecState *exec, const KJS::Identifier &propertyName) const;
214
215 KJS::Value getValueProperty(KJS::ExecState *exec, int token) const;
216
217 void put(KJS::ExecState *exec, const KJS::Identifier &propertyName, const KJS::Value& value, int attr = KJS::None);
218
219 void putValueProperty(KJS::ExecState *exec, int token, const KJS::Value& value, int attr);
220 */
221 const KJS::ClassInfo* classInfo() const { return &info; }
222
223 enum { OnChar,
224 OnLine,
225 OnNewline,
226 Dummy
227 };
228
229 public:
230
231 static const KJS::ClassInfo info;
232};
233
234#include "katejscript.lut.h"
235
236//END
237
238KateJScript::KateJScript ()
239 : m_global (new KJS::Object (new KateJSGlobal ()))
240 , m_interpreter (new KJS::Interpreter (*m_global))
241 , m_document (new KJS::Object(wrapDocument(m_interpreter->globalExec(), 0)))
242 , m_view (new KJS::Object (wrapView(m_interpreter->globalExec(), 0)))
243{
244 // put some stuff into env., this should stay for all executions, as we keep external
245 // references to the inserted KJS::Objects, this should avoid any garbage collection
246 m_interpreter->globalObject().put(m_interpreter->globalExec(), "document", *m_document);
247 m_interpreter->globalObject().put(m_interpreter->globalExec(), "view", *m_view);
248 m_interpreter->globalObject().put(m_interpreter->globalExec(), "debug",
249 KJS::Object(new KateJSGlobalFunctions(KateJSGlobalFunctions::Debug,1)));
250}
251
252KateJScript::~KateJScript ()
253{
254 delete m_view;
255 delete m_document;
256 delete m_interpreter;
257 delete m_global;
258}
259
260KJS::ObjectImp *KateJScript::wrapDocument (KJS::ExecState *exec, KateDocument *doc)
261{
262 return new KateJSDocument(exec, doc);
263}
264
265KJS::ObjectImp *KateJScript::wrapView (KJS::ExecState *exec, KateView *view)
266{
267 return new KateJSView(exec, view);
268}
269
270bool KateJScript::execute (KateView *view, const TQString &script, TQString &errorMsg)
271{
272 // no view, no fun
273 if (!view)
274 {
275 errorMsg = i18n("Could not access view");
276 return false;
277 }
278
279 // init doc & view with new pointers!
280 static_cast<KateJSDocument *>( m_document->imp() )->doc = view->doc();
281 static_cast<KateJSView *>( m_view->imp() )->view = view;
282
283 // run the script for real
284 KJS::Completion comp (m_interpreter->evaluate(script));
285
286 if (comp.complType() == KJS::Throw)
287 {
288 KJS::ExecState *exec = m_interpreter->globalExec();
289
290 KJS::Value exVal = comp.value();
291
292 char *msg = exVal.toString(exec).ascii();
293
294 int lineno = -1;
295
296 if (exVal.type() == KJS::ObjectType)
297 {
298 KJS::Value lineVal = KJS::Object::dynamicCast(exVal).get(exec,"line");
299
300 if (lineVal.type() == KJS::NumberType)
301 lineno = int(lineVal.toNumber(exec));
302 }
303
304 errorMsg = i18n("Exception, line %1: %2").arg(lineno).arg(msg);
305 return false;
306 }
307
308 return true;
309}
310
311//BEGIN KateJSDocument
312
313// -------------------------------------------------------------------------
314/* Source for KateJSDocumentProtoTable.
315@begin KateJSDocumentProtoTable 21
316#
317# edit interface stuff + editBegin/End, this is nice start
318#
319 textFull KateJSDocument::FullText DontDelete|Function 0
320 textRange KateJSDocument::Text DontDelete|Function 4
321 textLine KateJSDocument::TextLine DontDelete|Function 1
322 lines KateJSDocument::Lines DontDelete|Function 0
323 length KateJSDocument::Length DontDelete|Function 0
324 lineLength KateJSDocument::LineLength DontDelete|Function 1
325 setText KateJSDocument::SetText DontDelete|Function 1
326 clear KateJSDocument::Clear DontDelete|Function 0
327 insertText KateJSDocument::InsertText DontDelete|Function 3
328 removeText KateJSDocument::RemoveText DontDelete|Function 4
329 insertLine KateJSDocument::InsertLine DontDelete|Function 2
330 removeLine KateJSDocument::RemoveLine DontDelete|Function 1
331 editBegin KateJSDocument::EditBegin DontDelete|Function 0
332 editEnd KateJSDocument::EditEnd DontDelete|Function 0
333#
334# methods from highlight (and around)
335#
336 isInWord KateJSDocument::IsInWord DontDelete|Function 2
337 canBreakAt KateJSDocument::CanBreakAt DontDelete|Function 2
338 canComment KateJSDocument::CanComment DontDelete|Function 2
339 commentMarker KateJSDocument::CommentMarker DontDelete|Function 1
340 commentStart KateJSDocument::CommentStart DontDelete|Function 1
341 commentEnd KateJSDocument::CommentEnd DontDelete|Function 1
342 attribute KateJSDocument::Attribute DontDelete|Function 2
343@end
344
345@begin KateJSDocumentTable 6
346#
347# Configuration properties
348#
349 indentWidth KateJSDocument::IndentWidth DontDelete|ReadOnly
350 indentMode KateJSDocument::IndentMode DontDelete|ReadOnly
351 spaceIndent KateJSDocument::SpaceIndent DontDelete|ReadOnly
352 mixedIndent KateJSDocument::MixedIndent DontDelete|ReadOnly
353 highlightMode KateJSDocument::HighlightMode DontDelete|ReadOnly
354@end
355*/
356
357DEFINE_PROTOTYPE("KateJSDocument",KateJSDocumentProto)
358IMPLEMENT_PROTOFUNC(KateJSDocumentProtoFunc)
359IMPLEMENT_PROTOTYPE(KateJSDocumentProto,KateJSDocumentProtoFunc)
360
361const KJS::ClassInfo KateJSDocument::info = { "KateJSDocument", 0, 0, 0 };
362
363KJS::Value KJS::KateJSDocumentProtoFunc::call(KJS::ExecState *exec, KJS::Object &thisObj, const KJS::List &args)
364{
365 KJS_CHECK_THIS( KateJSDocument, thisObj );
366
367 KateDocument *doc = static_cast<KateJSDocument *>( thisObj.imp() )->doc;
368
369 if (!doc)
370 return KJS::Undefined();
371
372 switch (id)
373 {
374 case KateJSDocument::FullText:
375 return KJS::String (doc->text());
376
377 case KateJSDocument::Text:
378 return KJS::String (doc->text(args[0].toUInt32(exec), args[1].toUInt32(exec), args[2].toUInt32(exec), args[3].toUInt32(exec)));
379
380 case KateJSDocument::TextLine:
381 return KJS::String (doc->textLine (args[0].toUInt32(exec)));
382
383 case KateJSDocument::Lines:
384 return KJS::Number (doc->numLines());
385
386 case KateJSDocument::Length:
387 return KJS::Number (doc->length());
388
389 case KateJSDocument::LineLength:
390 return KJS::Number (doc->lineLength(args[0].toUInt32(exec)));
391
392 case KateJSDocument::SetText:
393 return KJS::Boolean (doc->setText(args[0].toString(exec).qstring()));
394
395 case KateJSDocument::Clear:
396 return KJS::Boolean (doc->clear());
397
398 case KateJSDocument::InsertText:
399 return KJS::Boolean (doc->insertText (args[0].toUInt32(exec), args[1].toUInt32(exec), args[2].toString(exec).qstring()));
400
401 case KateJSDocument::RemoveText:
402 return KJS::Boolean (doc->removeText(args[0].toUInt32(exec), args[1].toUInt32(exec), args[2].toUInt32(exec), args[3].toUInt32(exec)));
403
404 case KateJSDocument::InsertLine:
405 return KJS::Boolean (doc->insertLine (args[0].toUInt32(exec), args[1].toString(exec).qstring()));
406
407 case KateJSDocument::RemoveLine:
408 return KJS::Boolean (doc->removeLine (args[0].toUInt32(exec)));
409
410 case KateJSDocument::EditBegin:
411 doc->editBegin();
412 return KJS::Null ();
413
414 case KateJSDocument::EditEnd:
415 doc->editEnd ();
416 return KJS::Null ();
417
418 case KateJSDocument::IsInWord:
419 return KJS::Boolean( doc->highlight()->isInWord( args[0].toString(exec).qstring().at(0), args[1].toUInt32(exec) ) );
420
421 case KateJSDocument::CanBreakAt:
422 return KJS::Boolean( doc->highlight()->canBreakAt( args[0].toString(exec).qstring().at(0), args[1].toUInt32(exec) ) );
423
424 case KateJSDocument::CanComment:
425 return KJS::Boolean( doc->highlight()->canComment( args[0].toUInt32(exec), args[1].toUInt32(exec) ) );
426
427 case KateJSDocument::CommentMarker:
428 return KJS::String( doc->highlight()->getCommentSingleLineStart( args[0].toUInt32(exec) ) );
429
430 case KateJSDocument::CommentStart:
431 return KJS::String( doc->highlight()->getCommentStart( args[0].toUInt32(exec) ) );
432
433 case KateJSDocument::CommentEnd:
434 return KJS::String( doc->highlight()->getCommentEnd( args[0].toUInt32(exec) ) );
435
436 case KateJSDocument::Attribute:
437 return KJS::Number( doc->kateTextLine(args[0].toUInt32(exec))->attribute(args[1].toUInt32(exec)) );
438 }
439
440 return KJS::Undefined();
441}
442
443KJS::Value KateJSDocument::get( KJS::ExecState *exec, const KJS::Identifier &propertyName) const
444{
445 return KJS::lookupGetValue<KateJSDocument,KJS::ObjectImp>(exec, propertyName, &KateJSDocumentTable, this );
446}
447
448KJS::Value KateJSDocument::getValueProperty(KJS::ExecState *exec, int token) const
449{
450 if (!doc)
451 return KJS::Undefined ();
452
453 switch (token) {
454 case KateJSDocument::IndentWidth:
455 return KJS::Number( doc->config()->indentationWidth() );
456
457 case KateJSDocument::IndentMode:
458 return KJS::String( KateAutoIndent::modeName( doc->config()->indentationMode() ) );
459
460 case KateJSDocument::SpaceIndent:
461 return KJS::Boolean( doc->config()->configFlags() & KateDocumentConfig::cfSpaceIndent );
462
463 case KateJSDocument::MixedIndent:
464 return KJS::Boolean( doc->config()->configFlags() & KateDocumentConfig::cfMixedIndent );
465
466 case KateJSDocument::HighlightMode:
467 return KJS::String( doc->hlModeName( doc->hlMode() ) );
468 }
469
470 return KJS::Undefined ();
471}
472
473void KateJSDocument::put(KJS::ExecState *exec, const KJS::Identifier &propertyName, const KJS::Value& value, int attr)
474{
475 KJS::lookupPut<KateJSDocument,KJS::ObjectImp>(exec, propertyName, value, attr, &KateJSDocumentTable, this );
476}
477
478void KateJSDocument::putValueProperty(KJS::ExecState *exec, int token, const KJS::Value& value, int attr)
479{
480 if (!doc)
481 return;
482}
483
484KateJSDocument::KateJSDocument (KJS::ExecState *exec, KateDocument *_doc)
485 : KJS::ObjectImp (KateJSDocumentProto::self(exec))
486 , doc (_doc)
487{
488}
489
490//END
491
492//BEGIN KateJSView
493
494// -------------------------------------------------------------------------
495/* Source for KateJSViewProtoTable.
496@begin KateJSViewProtoTable 14
497 cursorLine KateJSView::CursorLine DontDelete|Function 0
498 cursorColumn KateJSView::CursorColumn DontDelete|Function 0
499 cursorColumnReal KateJSView::CursorColumnReal DontDelete|Function 0
500 setCursorPosition KateJSView::SetCursorPosition DontDelete|Function 2
501 setCursorPositionReal KateJSView::SetCursorPositionReal DontDelete|Function 2
502 selection KateJSView::Selection DontDelete|Function 0
503 hasSelection KateJSView::HasSelection DontDelete|Function 0
504 setSelection KateJSView::SetSelection DontDelete|Function 4
505 removeSelectedText KateJSView::RemoveSelectedText DontDelete|Function 0
506 selectAll KateJSView::SelectAll DontDelete|Function 0
507 clearSelection KateJSView::ClearSelection DontDelete|Function 0
508@end
509*/
510
511/* Source for KateJSViewTable.
512@begin KateJSViewTable 5
513 selectionStartLine KateJSView::SelStartLine DontDelete|ReadOnly
514 selectionStartColumn KateJSView::SelStartCol DontDelete|ReadOnly
515 selectionEndLine KateJSView::SelEndLine DontDelete|ReadOnly
516 selectionEndColumn KateJSView::SelEndCol DontDelete|ReadOnly
517@end
518*/
519
520DEFINE_PROTOTYPE("KateJSView",KateJSViewProto)
521IMPLEMENT_PROTOFUNC(KateJSViewProtoFunc)
522IMPLEMENT_PROTOTYPE(KateJSViewProto,KateJSViewProtoFunc)
523
524const KJS::ClassInfo KateJSView::info = { "KateJSView", 0, &KateJSViewTable, 0 };
525
526KJS::Value KJS::KateJSViewProtoFunc::call(KJS::ExecState *exec, KJS::Object &thisObj, const KJS::List &args)
527{
528 KJS_CHECK_THIS( KateJSView, thisObj );
529
530 KateView *view = static_cast<KateJSView *>( thisObj.imp() )->view;
531
532 if (!view)
533 return KJS::Undefined();
534
535 switch (id)
536 {
537 case KateJSView::CursorLine:
538 return KJS::Number (view->cursorLine());
539
540 case KateJSView::CursorColumn:
541 return KJS::Number (view->cursorColumn());
542
543 case KateJSView::CursorColumnReal:
544 return KJS::Number (view->cursorColumnReal());
545
546 case KateJSView::SetCursorPosition:
547 return KJS::Boolean( view->setCursorPosition( args[0].toUInt32(exec), args[1].toUInt32(exec) ) );
548
549 case KateJSView::SetCursorPositionReal:
550 return KJS::Boolean( view->setCursorPositionReal( args[0].toUInt32(exec), args[1].toUInt32(exec) ) );
551
552 // SelectionInterface goes in the view, in anticipation of the future
553 case KateJSView::Selection:
554 return KJS::String( view->selection() );
555
556 case KateJSView::HasSelection:
557 return KJS::Boolean( view->hasSelection() );
558
559 case KateJSView::SetSelection:
560 return KJS::Boolean( view->setSelection(args[0].toUInt32(exec),
561 args[1].toUInt32(exec),
562 args[2].toUInt32(exec),
563 args[3].toUInt32(exec)) );
564
565 case KateJSView::RemoveSelectedText:
566 return KJS::Boolean( view->removeSelectedText() );
567
568 case KateJSView::SelectAll:
569 return KJS::Boolean( view->selectAll() );
570
571 case KateJSView::ClearSelection:
572 return KJS::Boolean( view->clearSelection() );
573 }
574
575 return KJS::Undefined();
576}
577
578KateJSView::KateJSView (KJS::ExecState *exec, KateView *_view)
579 : KJS::ObjectImp (KateJSViewProto::self(exec))
580 , view (_view)
581{
582}
583
584KJS::Value KateJSView::get( KJS::ExecState *exec, const KJS::Identifier &propertyName) const
585{
586 return KJS::lookupGetValue<KateJSView,KJS::ObjectImp>(exec, propertyName, &KateJSViewTable, this );
587}
588
589KJS::Value KateJSView::getValueProperty(KJS::ExecState *exec, int token) const
590{
591 if (!view)
592 return KJS::Undefined ();
593
594 switch (token) {
595 case KateJSView::SelStartLine:
596 return KJS::Number( view->selStartLine() );
597
598 case KateJSView::SelStartCol:
599 return KJS::Number( view->selStartCol() );
600
601 case KateJSView::SelEndLine:
602 return KJS::Number( view->selEndLine() );
603
604 case KateJSView::SelEndCol:
605 return KJS::Number( view->selEndCol() );
606 }
607
608 return KJS::Undefined ();
609}
610
611void KateJSView::put(KJS::ExecState *exec, const KJS::Identifier &propertyName, const KJS::Value& value, int attr)
612{
613 KJS::lookupPut<KateJSView,KJS::ObjectImp>(exec, propertyName, value, attr, &KateJSViewTable, this );
614}
615
616void KateJSView::putValueProperty(KJS::ExecState *exec, int token, const KJS::Value& value, int attr)
617{
618 if (!view)
619 return;
620
621
622}
623
624//END
625
626//BEGIN KateJScriptManager
627
628KateJScriptManager::KateJScriptManager ()
629{
630 m_scripts.setAutoDelete (true);
631 collectScripts ();
632}
633
634KateJScriptManager::~KateJScriptManager ()
635{
636}
637
638void KateJScriptManager::collectScripts (bool force)
639{
640// If there's something in myModeList the Mode List was already built so, don't do it again
641 if (!m_scripts.isEmpty())
642 return;
643
644 // We'll store the scripts list in this config
645 TDEConfig config("katepartjscriptrc", false, false);
646
647 // figure out if the kate install is too new
648 config.setGroup ("General");
649 if (config.readNumEntry ("Version") > config.readNumEntry ("CachedVersion"))
650 {
651 config.writeEntry ("CachedVersion", config.readNumEntry ("Version"));
652 force = true;
653 }
654
655 // Let's get a list of all the .js files
656 TQStringList list = TDEGlobal::dirs()->findAllResources("data","katepart/scripts/*.js",false,true);
657
658 // Let's iterate through the list and build the Mode List
659 for ( TQStringList::Iterator it = list.begin(); it != list.end(); ++it )
660 {
661 // Each file has a group called:
662 TQString Group="Cache "+ *it;
663
664 // Let's go to this group
665 config.setGroup(Group);
666
667 // stat the file
668 struct stat sbuf;
669 memset (&sbuf, 0, sizeof(sbuf));
670 stat(TQFile::encodeName(*it), &sbuf);
671
672 // If the group exist and we're not forced to read the .js file, let's build myModeList for katepartjscriptrc
673 if (!force && config.hasGroup(Group) && (sbuf.st_mtime == config.readNumEntry("lastModified")))
674 {
675 }
676 else
677 {
678 kdDebug (13050) << "add script: " << *it << endl;
679
680 TQString desktopFile = (*it).left((*it).length()-2).append ("desktop");
681
682 kdDebug (13050) << "add script (desktop file): " << desktopFile << endl;
683
684 TQFileInfo dfi (desktopFile);
685
686 if (dfi.exists())
687 {
688 TDEConfig df (desktopFile, true, false);
689 df.setDesktopGroup ();
690
691 // get cmdname, fallback to baseName, if it is empty, therefor not use the tdeconfig fallback
692 TQString cmdname = df.readEntry ("X-Kate-Command");
693 if (cmdname.isEmpty())
694 {
695 TQFileInfo fi (*it);
696 cmdname = fi.baseName();
697 }
698
699 if (m_scripts[cmdname])
700 continue;
701
702 KateJScriptManager::Script *s = new KateJScriptManager::Script ();
703
704 s->name = cmdname;
705 s->filename = *it;
706 s->desktopFileExists = true;
707
708 m_scripts.insert (s->name, s);
709 }
710 else // no desktop file around, fall back to scriptfilename == commandname
711 {
712 kdDebug (13050) << "add script: fallback, no desktop file around!" << endl;
713
714 TQFileInfo fi (*it);
715
716 if (m_scripts[fi.baseName()])
717 continue;
718
719 KateJScriptManager::Script *s = new KateJScriptManager::Script ();
720
721 s->name = fi.baseName();
722 s->filename = *it;
723 s->desktopFileExists = false;
724
725 m_scripts.insert (s->name, s);
726 }
727 }
728 }
729
730 // Syncronize with the file katepartjscriptrc
731 config.sync();
732}
733
734bool KateJScriptManager::exec( Kate::View *view, const TQString &_cmd, TQString &errorMsg )
735{
736 // cast it hardcore, we know that it is really a kateview :)
737 KateView *v = (KateView*) view;
738
739 if ( !v )
740 {
741 errorMsg = i18n("Could not access view");
742 return false;
743 }
744
745 //create a list of args
746 TQStringList args( TQStringList::split( TQRegExp("\\s+"), _cmd ) );
747 TQString cmd ( args.first() );
748 args.remove( args.first() );
749
750 kdDebug(13050) << "try to exec: " << cmd << endl;
751
752 if (!m_scripts[cmd])
753 {
754 errorMsg = i18n("Command not found");
755 return false;
756 }
757
758 TQFile file (m_scripts[cmd]->filename);
759
760 if ( !file.open( IO_ReadOnly ) )
761 {
762 errorMsg = i18n("JavaScript file not found");
763 return false;
764 }
765
766 TQTextStream stream( &file );
767 stream.setEncoding (TQTextStream::UnicodeUTF8);
768
769 TQString source = stream.read ();
770
771 file.close();
772
773 return KateFactory::self()->jscript()->execute(v, source, errorMsg);
774}
775
776bool KateJScriptManager::help( Kate::View *, const TQString &cmd, TQString &msg )
777{
778 if (!m_scripts[cmd] || !m_scripts[cmd]->desktopFileExists)
779 return false;
780
781 TDEConfig df (m_scripts[cmd]->desktopFilename(), true, false);
782 df.setDesktopGroup ();
783
784 msg = df.readEntry ("X-Kate-Help");
785
786 if (msg.isEmpty())
787 return false;
788
789 return true;
790}
791
792TQStringList KateJScriptManager::cmds()
793{
794 TQStringList l;
795
796 TQDictIterator<KateJScriptManager::Script> it( m_scripts );
797 for( ; it.current(); ++it )
798 l << it.current()->name;
799
800 return l;
801}
802
803//END
804
805
806
807
808//BEGIN KateJSIndenter
809
810// -------------------------------------------------------------------------
811/* Source for KateJSIndenterProtoTable.
812@begin KateJSIndenterProtoTable 1
813 Dummy KateJSIndenter::Dummy DontDelete
814@end
815*/
816
817/* Source for KateJSIndenterTable.
818@begin KateJSIndenterTable 3
819 onchar KateJSIndenter::OnChar DontDelete
820 onnewline KateJSIndenter::OnNewline DontDelete
821 online KateJSIndenter::OnLine DontDelete
822
823@end
824*/
825
826KateJSIndenter::KateJSIndenter (KJS::ExecState *exec)
827 : KJS::ObjectImp (KateJSViewProto::self(exec))
828{
829}
830
831DEFINE_PROTOTYPE("KateJSIndenter",KateJSIndenterProto)
832IMPLEMENT_PROTOFUNC(KateJSIndenterProtoFunc)
833IMPLEMENT_PROTOTYPE(KateJSIndenterProto,KateJSIndenterProtoFunc)
834
835const KJS::ClassInfo KateJSIndenter::info = { "KateJSIndenter", 0, &KateJSIndenterTable, 0 };
836
837KJS::Value KJS::KateJSIndenterProtoFunc::call(KJS::ExecState *exec, KJS::Object &thisObj, const KJS::List &args)
838{
839 KJS_CHECK_THIS( KateJSIndenter, thisObj );
840
841 return KJS::Undefined();
842}
843
844//END
845
846//BEGIN KateIndentJScriptImpl
847KateIndentJScriptImpl::KateIndentJScriptImpl(const TQString& internalName,
848 const TQString &filePath, const TQString &niceName,
849 const TQString &copyright, double version):
850 KateIndentScriptImplAbstract(internalName,filePath,niceName,copyright,version),m_interpreter(0),m_indenter(0)
851{
852}
853
854
855KateIndentJScriptImpl::~KateIndentJScriptImpl()
856{
857 deleteInterpreter();
858}
859
860void KateIndentJScriptImpl::decRef()
861{
862 KateIndentScriptImplAbstract::decRef();
863 if (refCount()==0)
864 {
865 deleteInterpreter();
866 }
867}
868
869void KateIndentJScriptImpl::deleteInterpreter()
870{
871 m_docWrapper=0;
872 m_viewWrapper=0;
873 delete m_indenter;
874 m_indenter=0;
875 delete m_interpreter;
876 m_interpreter=0;
877}
878
879bool KateIndentJScriptImpl::setupInterpreter(TQString &errorMsg)
880{
881 if (!m_interpreter)
882 {
883 kdDebug(13050)<<"Setting up interpreter"<<endl;
884 m_interpreter=new KJS::Interpreter(KJS::Object(new KateJSGlobal()));
885 m_docWrapper=new KateJSDocument(m_interpreter->globalExec(),0);
886 m_viewWrapper=new KateJSView(m_interpreter->globalExec(),0);
887 m_indenter=new KJS::Object(new KateJSIndenter(m_interpreter->globalExec()));
888 m_interpreter->globalObject().put(m_interpreter->globalExec(),"document",KJS::Object(m_docWrapper),KJS::DontDelete | KJS::ReadOnly);
889 m_interpreter->globalObject().put(m_interpreter->globalExec(),"view",KJS::Object(m_viewWrapper),KJS::DontDelete | KJS::ReadOnly);
890 m_interpreter->globalObject().put(m_interpreter->globalExec(),"debug", KJS::Object(new
891 KateJSGlobalFunctions(KateJSGlobalFunctions::Debug,1)));
892 m_interpreter->globalObject().put(m_interpreter->globalExec(),"indenter",*m_indenter,KJS::DontDelete | KJS::ReadOnly);
893 TQFile file (filePath());
894
895 if ( !file.open( IO_ReadOnly ) )
896 {
897 errorMsg = i18n("JavaScript file not found");
898 deleteInterpreter();
899 return false;
900 }
901
902 TQTextStream stream( &file );
903 stream.setEncoding (TQTextStream::UnicodeUTF8);
904
905 TQString source = stream.read ();
906
907 file.close();
908
909 KJS::Completion comp (m_interpreter->evaluate(source));
910 if (comp.complType() == KJS::Throw)
911 {
912 KJS::ExecState *exec = m_interpreter->globalExec();
913
914 KJS::Value exVal = comp.value();
915
916 char *msg = exVal.toString(exec).ascii();
917
918 int lineno = -1;
919
920 if (exVal.type() == KJS::ObjectType)
921 {
922 KJS::Value lineVal = KJS::Object::dynamicCast(exVal).get(exec,"line");
923
924 if (lineVal.type() == KJS::NumberType)
925 lineno = int(lineVal.toNumber(exec));
926 }
927
928 errorMsg = i18n("Exception, line %1: %2").arg(lineno).arg(msg);
929 deleteInterpreter();
930 return false;
931 } else {
932 return true;
933 }
934 } else return true;
935}
936
937
938inline static bool KateIndentJScriptCall(Kate::View *view, TQString &errorMsg, KateJSDocument *docWrapper, KateJSView *viewWrapper,
939 KJS::Interpreter *interpreter, KJS::Object lookupobj,const KJS::Identifier& func,KJS::List params)
940{
941 // no view, no fun
942 if (!view)
943 {
944 errorMsg = i18n("Could not access view");
945 return false;
946 }
947
948 KateView *v=(KateView*)view;
949
950 KJS::Object o=lookupobj.get(interpreter->globalExec(),func).toObject(interpreter->globalExec());
951 if (interpreter->globalExec()->hadException())
952 {
953 errorMsg=interpreter->globalExec()->exception().toString(interpreter->globalExec()).qstring();
954 kdDebug(13050)<<"Exception(1):"<<errorMsg<<endl;
955 interpreter->globalExec()->clearException();
956 return false;
957 }
958
959 // init doc & view with new pointers!
960 docWrapper->doc = v->doc();
961 viewWrapper->view = v;
962
963 /*kdDebug(13050)<<"Call Object:"<<o.toString(interpreter->globalExec()).ascii()<<endl;*/
964 o.call(interpreter->globalExec(),interpreter->globalObject(),params);
965 if (interpreter->globalExec()->hadException())
966 {
967 errorMsg=interpreter->globalExec()->exception().toString(interpreter->globalExec()).ascii();
968 kdDebug(13050)<<"Exception(2):"<<errorMsg<<endl;
969 interpreter->globalExec()->clearException();
970 return false;
971 }
972 return true;
973}
974
975bool KateIndentJScriptImpl::processChar(Kate::View *view, TQChar c, TQString &errorMsg )
976{
977
978 kdDebug(13050)<<"KateIndentJScriptImpl::processChar"<<endl;
979 if (!setupInterpreter(errorMsg)) return false;
980 KJS::List params;
981 params.append(KJS::String(TQString(c)));
982 return KateIndentJScriptCall(view,errorMsg,m_docWrapper,m_viewWrapper,m_interpreter,*m_indenter,KJS::Identifier("onchar"),params);
983}
984
985bool KateIndentJScriptImpl::processLine(Kate::View *view, const KateDocCursor &line, TQString &errorMsg )
986{
987 kdDebug(13050)<<"KateIndentJScriptImpl::processLine"<<endl;
988 if (!setupInterpreter(errorMsg)) return false;
989 return KateIndentJScriptCall(view,errorMsg,m_docWrapper,m_viewWrapper,m_interpreter,*m_indenter,KJS::Identifier("online"),KJS::List());
990}
991
992bool KateIndentJScriptImpl::processNewline( class Kate::View *view, const KateDocCursor &begin, bool needcontinue, TQString &errorMsg )
993{
994 kdDebug(13050)<<"KateIndentJScriptImpl::processNewline"<<endl;
995 if (!setupInterpreter(errorMsg)) return false;
996 return KateIndentJScriptCall(view,errorMsg,m_docWrapper,m_viewWrapper,m_interpreter,*m_indenter,KJS::Identifier("onnewline"),KJS::List());
997}
998//END
999
1000//BEGIN KateIndentJScriptManager
1001KateIndentJScriptManager::KateIndentJScriptManager():KateIndentScriptManagerAbstract()
1002{
1003 m_scripts.setAutoDelete (true);
1004 collectScripts ();
1005}
1006
1007KateIndentJScriptManager::~KateIndentJScriptManager ()
1008{
1009}
1010
1011void KateIndentJScriptManager::collectScripts (bool force)
1012{
1013// If there's something in myModeList the Mode List was already built so, don't do it again
1014 if (!m_scripts.isEmpty())
1015 return;
1016
1017
1018 // We'll store the scripts list in this config
1019 TDEConfig config("katepartindentjscriptrc", false, false);
1020#if 0
1021 // figure out if the kate install is too new
1022 config.setGroup ("General");
1023 if (config.readNumEntry ("Version") > config.readNumEntry ("CachedVersion"))
1024 {
1025 config.writeEntry ("CachedVersion", config.readNumEntry ("Version"));
1026 force = true;
1027 }
1028#endif
1029
1030 // Let's get a list of all the .js files
1031 TQStringList list = TDEGlobal::dirs()->findAllResources("data","katepart/scripts/indent/*.js",false,true);
1032
1033 // Let's iterate through the list and build the Mode List
1034 for ( TQStringList::Iterator it = list.begin(); it != list.end(); ++it )
1035 {
1036 // Each file has a group ed:
1037 TQString Group="Cache "+ *it;
1038
1039 // Let's go to this group
1040 config.setGroup(Group);
1041
1042 // stat the file
1043 struct stat sbuf;
1044 memset (&sbuf, 0, sizeof(sbuf));
1045 stat(TQFile::encodeName(*it), &sbuf);
1046
1047 // If the group exist and we're not forced to read the .js file, let's build myModeList for katepartjscriptrc
1048 bool readnew=false;
1049 if (!force && config.hasGroup(Group) && (sbuf.st_mtime == config.readNumEntry("lastModified")))
1050 {
1051 config.setGroup(Group);
1052 TQString filePath=*it;
1053 TQString internalName=config.readEntry("internlName","KATE-ERROR");
1054 if (internalName=="KATE-ERROR") readnew=true;
1055 else
1056 {
1057 TQString niceName=config.readEntry("niceName",internalName);
1058 TQString copyright=config.readEntry("copyright",i18n("(Unknown)"));
1059 double version=config.readDoubleNumEntry("version",0.0);
1060 KateIndentJScriptImpl *s=new KateIndentJScriptImpl(
1061 internalName,filePath,niceName,copyright,version);
1062 m_scripts.insert (internalName, s);
1063 }
1064 }
1065 else readnew=true;
1066 if (readnew)
1067 {
1068 TQFileInfo fi (*it);
1069
1070 if (m_scripts[fi.baseName()])
1071 continue;
1072
1073 TQString internalName=fi.baseName();
1074 TQString filePath=*it;
1075 TQString niceName=internalName;
1076 TQString copyright=i18n("(Unknown)");
1077 double version=0.0;
1078 parseScriptHeader(filePath,&niceName,&copyright,&version);
1079 /*save the information for retrieval*/
1080 config.setGroup(Group);
1081 config.writeEntry("lastModified",sbuf.st_mtime);
1082 config.writeEntry("internalName",internalName);
1083 config.writeEntry("niceName",niceName);
1084 config.writeEntry("copyright",copyright);
1085 config.writeEntry("version",version);
1086 KateIndentJScriptImpl *s=new KateIndentJScriptImpl(
1087 internalName,filePath,niceName,copyright,version);
1088 m_scripts.insert (internalName, s);
1089 }
1090 }
1091
1092 // Syncronize with the file katepartjscriptrc
1093 config.sync();
1094}
1095
1096KateIndentScript KateIndentJScriptManager::script(const TQString &scriptname) {
1097 KateIndentJScriptImpl *s=m_scripts[scriptname];
1098 kdDebug(13050)<<scriptname<<"=="<<s<<endl;
1099 return KateIndentScript(s);
1100}
1101
1102void KateIndentJScriptManager::parseScriptHeader(const TQString &filePath,
1103 TQString *niceName,TQString *copyright,double *version)
1104{
1105 TQFile f(TQFile::encodeName(filePath));
1106 if (!f.open(IO_ReadOnly) ) {
1107 kdDebug(13050)<<"Header could not be parsed, because file could not be opened"<<endl;
1108 return;
1109 }
1110 TQTextStream st(&f);
1111 st.setEncoding (TQTextStream::UnicodeUTF8);
1112 if (!st.readLine().upper().startsWith("/**KATE")) {
1113 kdDebug(13050)<<"No header found"<<endl;
1114 f.close();
1115 return;
1116 }
1117 // here the real parsing begins
1118 kdDebug(13050)<<"Parsing indent script header"<<endl;
1119 enum {NOTHING=0,COPYRIGHT=1} currentState=NOTHING;
1120 TQString line;
1121 TQString tmpblockdata="";
1122 TQRegExp endExpr("[\\s\\t]*\\*\\*\\/[\\s\\t]*$");
1123 TQRegExp keyValue("[\\s\\t]*\\*\\s*(.+):(.*)$");
1124 TQRegExp blockContent("[\\s\\t]*\\*(.*)$");
1125 while ((line=st.readLine())!=TQString::null) {
1126 if (endExpr.exactMatch(line)) {
1127 kdDebug(13050)<<"end of config block"<<endl;
1128 if (currentState==NOTHING) break;
1129 if (currentState==COPYRIGHT) {
1130 *copyright=tmpblockdata;
1131 break;
1132 }
1133 Q_ASSERT(0);
1134 }
1135 if (currentState==NOTHING)
1136 {
1137 if (keyValue.exactMatch(line)) {
1138 TQStringList sl=keyValue.capturedTexts();
1139 kdDebug(13050)<<"key:"<<sl[1]<<endl<<"value:"<<sl[2]<<endl;
1140 kdDebug(13050)<<"key-length:"<<sl[1].length()<<endl<<"value-length:"<<sl[2].length()<<endl;
1141 TQString key=sl[1];
1142 TQString value=sl[2];
1143 if (key=="NAME") (*niceName)=value.stripWhiteSpace();
1144 else if (key=="VERSION") (*version)=value.stripWhiteSpace().toDouble(0);
1145 else if (key=="COPYRIGHT")
1146 {
1147 tmpblockdata="";
1148 if (value.stripWhiteSpace().length()>0) tmpblockdata=value;
1149 currentState=COPYRIGHT;
1150 } else kdDebug(13050)<<"ignoring key"<<endl;
1151 }
1152 } else {
1153 if (blockContent.exactMatch(line))
1154 {
1155 TQString bl=blockContent.capturedTexts()[1];
1156 //kdDebug(13050)<<"block content line:"<<bl<<endl<<bl.length()<<" "<<bl.isEmpty()<<endl;
1157 if (bl.isEmpty())
1158 {
1159 (*copyright)=tmpblockdata;
1160 kdDebug(13050)<<"Copyright block:"<<endl<<(*copyright)<<endl;
1161 currentState=NOTHING;
1162 } else tmpblockdata=tmpblockdata+"\n"+bl;
1163 }
1164 }
1165 }
1166 f.close();
1167}
1168//END
KateAutoIndent::modeName
static TQString modeName(uint mode)
Return the mode name given the mode.
Definition: kateautoindent.cpp:74
KateDocCursor
Cursor class with a pointer to its document.
Definition: katecursor.h:93
KateJScript::m_global
KJS::Object * m_global
global object of interpreter
Definition: katejscript.h:96
KateJScript::wrapView
KJS::ObjectImp * wrapView(KJS::ExecState *exec, KateView *view)
creates a JS wrapper object for given KateView
Definition: katejscript.cpp:265
KateJScript::execute
bool execute(KateView *view, const TQString &script, TQString &errorMsg)
execute given script the script will get the doc and view exposed via document and view object in glo...
Definition: katejscript.cpp:270
KateJScript::m_interpreter
KJS::Interpreter * m_interpreter
js interpreter
Definition: katejscript.h:101
KateJScript::m_document
KJS::Object * m_document
object for document
Definition: katejscript.h:106
KateJScript::wrapDocument
KJS::ObjectImp * wrapDocument(KJS::ExecState *exec, KateDocument *doc)
creates a JS wrapper object for given KateDocument
Definition: katejscript.cpp:260
KateJScript::m_view
KJS::Object * m_view
object for view
Definition: katejscript.h:111
KateJScript::KateJScript
KateJScript()
generate new global interpreter for part scripting
Definition: katejscript.cpp:238
KateJScript::~KateJScript
virtual ~KateJScript()
be destructive
Definition: katejscript.cpp:252
Kate::View
The Kate::View text editor interface.
Definition: view.h:45
TDEConfig
TDEGlobal::dirs
static TDEStandardDirs * dirs()
TDEStandardDirs::findAllResources
TQStringList findAllResources(const char *type, const TQString &filter=TQString::null, bool recursive=false, bool unique=false) const
endl
kndbgstream & endl(kndbgstream &s)
kdDebug
kdbgstream kdDebug(int area=0)
KDE::version
unsigned int version()
KJS
Cool, this is all we need here.
Definition: katejscript.cpp:53
KStdAction::Clear
Clear
TDEStdAccel::key
int key(StdAccel id)
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.