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

kate

  • kate
  • part
kateluaindentscript.cpp
1/* This file is part of the KDE libraries
2 Copyright (C) 2005 Joseph Wenninger <jowenn@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License version 2 as published by the Free Software Foundation.
7
8 This library is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 Library General Public License for more details.
12
13 You should have received a copy of the GNU Library General Public License
14 along with this library; see the file COPYING.LIB. If not, write to
15 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
16 Boston, MA 02110-1301, USA.
17*/
18
19#include "config.h"
20#ifdef HAVE_LUA
21
22#include "kateluaindentscript.h"
23#include "katedocument.h"
24#include "kateview.h"
25
26#include <sys/types.h>
27#include <sys/stat.h>
28#include <unistd.h>
29
30#include <tqfile.h>
31#include <tqfileinfo.h>
32#include <tdestandarddirs.h>
33
34#include <tdeconfig.h>
35#include <tdeglobal.h>
36#include <tdelocale.h>
37
38extern "C" {
39#include <lua.h>
40#include <lualib.h>
41}
42
43#define ONCHAR 1
44#define ONNEWLINE 2
45#define ONCHARSTR "kateonchar"
46#define ONNEWLINESTR "kateonnewline"
47
48#define katelua_registerFunc(n,f,t) \
49 (lua_pushstring(m_interpreter, n), \
50 lua_pushcfunction(m_interpreter, f), \
51 lua_settable(m_interpreter, t))
52
53#define katelua_registerNumConst(n,v,t) \
54 (lua_pushstring(m_interpreter, n), \
55 lua_pushnumber(m_interpreter, v), \
56 lua_settable(m_interpreter, t))
57
58//BEGIN temporary, try to use registry later
59static KateDocument *katelua_doc;
60static Kate::View *katelua_view;
61//END
62
63
64
65//BEGIN STATIC BINDING FUNCTIONS
66typedef struct KATELUA_FUNCTIONS {
67 char *name;
68 lua_CFunction func;
69} KATELUA_FUNCTIONS;
70
71static int katelua_katedebug(lua_State *L) {
72 int n=lua_gettop(L);
73 for (int i=1;i<=n;i++) {
74 if (lua_isnil(L,i)) kdDebug()<<"NIL VALUE"<<endl;
75 else if (lua_isstring(L,i)) kdDebug()<<lua_tostring(L,i)<<endl;
76 else if (lua_isboolean(L,i)) kdDebug()<<(bool)lua_toboolean(L,i)<<endl;
77 else if (lua_isnumber(L,i)) kdDebug()<<lua_tonumber(L,i)<<endl;
78 else kdDebug()<<"Invalid type for katedebug:"<<lua_type(L,i)<<endl;
79 }
80 return 0;
81}
82
83static int katelua_indenter_register(lua_State *L) {
84 int n=lua_gettop(L);
85 if (n!=2) {
86 lua_pushstring(L,i18n("indenter.register requires 2 parameters (event id, function to call)").utf8().data());
87 lua_error(L);
88 }
89 if ( (!lua_isfunction(L,2)) || (!lua_isnumber(L,1)))
90 {
91 /*if (lua_isnumber(L,1)) kdDebug()<<"A"<<endl;
92 if (lua_isfunction(L,2)) kdDebug()<<"B"<<endl;
93 kdDebug()<<lua_type(L,2)<<endl;*/
94 lua_pushstring(L,i18n("indenter.register requires 2 parameters (event id (number), function to call (function))").utf8().data());
95 lua_error(L);
96 }
97 switch ((int)lua_tonumber(L,1))
98 {
99 case ONCHAR:
100 lua_pushstring(L,ONCHARSTR);
101 lua_pushstring(L,ONCHARSTR);
102 break;
103 case ONNEWLINE:
104 lua_pushstring(L,ONNEWLINESTR);
105 lua_pushstring(L,ONNEWLINESTR);
106 break;
107 default:
108 lua_pushstring(L,i18n("indenter.register:invalid event id").utf8().data());
109 lua_error(L);
110 }
111 lua_gettable(L,LUA_REGISTRYINDEX);
112 if (!lua_isnil(L,lua_gettop(L))) {
113 lua_pushstring(L,i18n("indenter.register:there is already a function set for given").utf8().data());
114 lua_error(L);
115 }
116 lua_pop(L,1);
117 lua_pushvalue(L,2);
118 lua_settable(L,LUA_REGISTRYINDEX);
119 kdDebug()<<"katelua_indenter_register: Success"<<endl;
120 return 0;
121}
122
123
124static int katelua_document_textline(lua_State *L) {
125 if (lua_gettop(L)!=1) {
126 lua_pushstring(L,i18n("document.textLine:One parameter (line number) required").utf8().data());
127 lua_error(L);
128 }
129 if (!lua_isnumber(L,1)) {
130 lua_pushstring(L,i18n("document.textLine:One parameter (line number) required (number)").utf8().data());
131 lua_error(L);
132 }
133 lua_pushstring(L,katelua_doc->textLine((uint)lua_tonumber(L,1)).utf8().data());
134 return 1;
135}
136
137static int katelua_document_removeText(lua_State *L) {
138 if (lua_gettop(L)!=4) {
139 lua_pushstring(L,i18n("document.removeText:Four parameters needed (start line, start col,end line, end col)").utf8().data());
140 lua_error(L);
141 }
142 if ((!lua_isnumber(L,1)) || (!lua_isnumber(L,2)) ||(!lua_isnumber(L,3)) || (!lua_isnumber(L,4))) {
143 lua_pushstring(L,i18n("document.removeText:Four parameters needed (start line, start col,end line, end col) (4x number)").utf8().data());
144 lua_error(L);
145 }
146 lua_pushboolean(L,katelua_doc->removeText((uint)lua_tonumber(L,1),(uint)lua_tonumber(L,2),(uint)lua_tonumber(L,3),(uint)lua_tonumber(L,4)));
147 return 1;
148}
149
150static int katelua_document_insertText(lua_State *L) {
151 if (lua_gettop(L)!=3) {
152 lua_pushstring(L,i18n("document.insertText:Three parameters needed (line,col,text)").utf8().data());
153 lua_error(L);
154 }
155 if ((!lua_isnumber(L,1)) || (!lua_isnumber(L,2)) ||(!lua_isstring(L,3)) ) {
156 lua_pushstring(L,i18n("document.insertText:Three parameters needed (line,col,text) (number,number,string)").utf8().data());
157 lua_error(L);
158 }
159 lua_pushboolean(L,katelua_doc->insertText((uint)lua_tonumber(L,1),(uint)lua_tonumber(L,2),TQString::fromUtf8(lua_tostring(L,3))));
160 return 1;
161}
162
163static int katelua_view_cursorline(lua_State *L) {
164 lua_pushnumber(L,katelua_view->cursorLine());
165 return 1;
166}
167static int katelua_view_cursorcolumn(lua_State *L) {
168 lua_pushnumber(L,katelua_view->cursorColumn());
169 return 1;
170}
171static int katelua_view_cursorposition(lua_State *L) {
172 lua_pushnumber(L,katelua_view->cursorLine());
173 lua_pushnumber(L,katelua_view->cursorColumn());
174 return 2;
175
176}
177static int katelua_view_setcursorpositionreal(lua_State *L) {
178 return 0;
179}
180
181static const struct KATELUA_FUNCTIONS katelua_documenttable[4]= {
182{"textLine",katelua_document_textline},
183{"removeText",katelua_document_removeText},
184{"insertText",katelua_document_insertText},
185{0,0}
186};
187
188static const struct KATELUA_FUNCTIONS katelua_viewtable[5]= {
189{"cursorLine",katelua_view_cursorline},
190{"cursorColumn",katelua_view_cursorcolumn},
191{"cursorPosition",katelua_view_cursorposition},
192{"setCursorPositionReal",katelua_view_setcursorpositionreal},
193{0,0}
194};
195
196static void kateregistertable(lua_State* m_interpreter,const KATELUA_FUNCTIONS funcs[],char * tablename) {
197 lua_newtable(m_interpreter);
198 int table=lua_gettop(m_interpreter);
199 for (uint i=0;funcs[i].name!=0;i++)
200 {
201 katelua_registerFunc(funcs[i].name,funcs[i].func,table);
202 }
203
204 lua_pushstring(m_interpreter,tablename);
205 lua_pushvalue(m_interpreter,table);
206 lua_settable(m_interpreter,LUA_GLOBALSINDEX);
207 lua_pop(m_interpreter,1);
208
209}
210
211//END STATIC BINDING FUNCTIONS
212
213
214//BEGIN KateLUAIndentScriptImpl
215KateLUAIndentScriptImpl::KateLUAIndentScriptImpl(const TQString& internalName,
216 const TQString &filePath, const TQString &niceName,
217 const TQString &copyright, double version):
218 KateIndentScriptImplAbstract(internalName,filePath,niceName,copyright,version),m_interpreter(0)/*,m_indenter(0)*/
219{
220}
221
222
223KateLUAIndentScriptImpl::~KateLUAIndentScriptImpl()
224{
225 deleteInterpreter();
226}
227
228void KateLUAIndentScriptImpl::decRef()
229{
230 KateIndentScriptImplAbstract::decRef();
231 if (refCount()==0)
232 {
233 deleteInterpreter();
234 }
235}
236
237void KateLUAIndentScriptImpl::deleteInterpreter()
238{
239 if (m_interpreter)
240 {
241 lua_close(m_interpreter);
242 m_interpreter=0;
243 }
244}
245
246bool KateLUAIndentScriptImpl::setupInterpreter(TQString &errorMsg)
247{
248 if (m_interpreter) return true;
249 m_interpreter=lua_open();
250
251 if (!m_interpreter)
252 {
253 errorMsg=i18n("LUA interpreter could not be initialized");
254 return false;
255 }
256 luaopen_base(m_interpreter);
257 luaopen_string( m_interpreter );
258 luaopen_table( m_interpreter );
259 luaopen_math( m_interpreter );
260 luaopen_io( m_interpreter );
261 luaopen_debug( m_interpreter );
262
263
264 /*indenter callback setup table*/
265 lua_newtable(m_interpreter);
266 int indentertable=lua_gettop(m_interpreter);
267 katelua_registerFunc("register",katelua_indenter_register,indentertable);
268 katelua_registerNumConst("OnChar",ONCHAR,indentertable);
269 katelua_registerNumConst("OnNewline",ONNEWLINE,indentertable);
270 lua_pushstring(m_interpreter,"indenter");
271 lua_pushvalue(m_interpreter,indentertable);
272 lua_settable(m_interpreter,LUA_GLOBALSINDEX);
273 lua_pop(m_interpreter,1);
274
275 /*debug*/
276 katelua_registerFunc("katedebug",katelua_katedebug,LUA_GLOBALSINDEX);
277
278 /*document interface*/
279 kateregistertable(m_interpreter,katelua_documenttable,"document");
280 /*view interface*/
281 kateregistertable(m_interpreter,katelua_viewtable,"view");
282
283 /*open script*/
284 lua_pushstring(m_interpreter,"dofile");
285 lua_gettable(m_interpreter,LUA_GLOBALSINDEX);
286 TQCString fn=TQFile::encodeName(filePath());
287 lua_pushstring(m_interpreter,fn.data());
288 int execresult=lua_pcall(m_interpreter,1,1,0);
289 if (execresult==0) {
290 kdDebug()<<"Lua script has been loaded successfully. Lua interpreter version:"<<lua_version()<<endl;
291 return true;
292 } else {
293 errorMsg=i18n("Lua indenting script had errors: %1").arg(lua_tostring(m_interpreter,lua_gettop(m_interpreter)));
294 kdDebug()<<errorMsg<<endl;
295 deleteInterpreter();
296
297 return false;
298 }
299}
300
301
302bool KateLUAIndentScriptImpl::processChar(Kate::View *view, TQChar c, TQString &errorMsg )
303{
304 if (!setupInterpreter(errorMsg)) return false;
305 katelua_doc=((KateView*)view)->doc();
306 katelua_view=view;
307 int oldtop=lua_gettop(m_interpreter);
308 lua_pushstring(m_interpreter,ONCHARSTR);
309 lua_gettable(m_interpreter,LUA_REGISTRYINDEX);
310 bool result=true;
311 if (!lua_isnil(m_interpreter,lua_gettop(m_interpreter)))
312 {
313 lua_pushstring(m_interpreter,TQString(c).utf8().data());
314 if (lua_pcall(m_interpreter,1,0,0)!=0)
315 {
316 errorMsg=i18n("Lua indenting script had errors: %1").arg(lua_tostring(m_interpreter,lua_gettop(m_interpreter)));
317 kdDebug()<<errorMsg<<endl;
318 result=false;
319 }
320 }
321 lua_settop(m_interpreter,oldtop);
322 return result;
323}
324
325bool KateLUAIndentScriptImpl::processLine(Kate::View *view, const KateDocCursor &line, TQString &errorMsg )
326{
327 if (!setupInterpreter(errorMsg)) return false;
328 return true;
329}
330
331bool KateLUAIndentScriptImpl::processNewline( class Kate::View *view, const KateDocCursor &begin, bool needcontinue, TQString &errorMsg )
332{
333 if (!setupInterpreter(errorMsg)) return false;
334 katelua_doc=((KateView*)view)->doc();
335 katelua_view=view;
336 int oldtop=lua_gettop(m_interpreter);
337 lua_pushstring(m_interpreter,ONNEWLINESTR);
338 lua_gettable(m_interpreter,LUA_REGISTRYINDEX);
339 bool result=true;
340 if (!lua_isnil(m_interpreter,lua_gettop(m_interpreter)))
341 {
342 if (lua_pcall(m_interpreter,0,0,0)!=0)
343 {
344 errorMsg=i18n("Lua indenting script had errors: %1").arg(lua_tostring(m_interpreter,lua_gettop(m_interpreter)));
345 kdDebug()<<errorMsg<<endl;
346 result=false;
347 }
348 }
349 lua_settop(m_interpreter,oldtop);
350 return result;
351}
352//END
353
354//BEGIN KateLUAIndentScriptManager
355KateLUAIndentScriptManager::KateLUAIndentScriptManager():KateIndentScriptManagerAbstract()
356{
357 collectScripts();
358}
359
360KateLUAIndentScriptManager::~KateLUAIndentScriptManager ()
361{
362}
363
364void KateLUAIndentScriptManager::collectScripts (bool force)
365{
366// If there's something in myModeList the Mode List was already built so, don't do it again
367 if (!m_scripts.isEmpty())
368 return;
369
370 kdDebug()<<"================================================="<<endl<<"Trying to find Lua scripts"<<endl
371 <<"================================================="<<endl;
372
373 // We'll store the scripts list in this config
374 TDEConfig config("katepartluaindentscriptrc", false, false);
375#if 0
376 // figure out if the kate install is too new
377 config.setGroup ("General");
378 if (config.readNumEntry ("Version") > config.readNumEntry ("CachedVersion"))
379 {
380 config.writeEntry ("CachedVersion", config.readNumEntry ("Version"));
381 force = true;
382 }
383#endif
384
385 // Let's get a list of all the .js files
386 TQStringList list = TDEGlobal::dirs()->findAllResources("data","katepart/scripts/indent/*.lua",false,true);
387
388 // Let's iterate through the list and build the Mode List
389 for ( TQStringList::Iterator it = list.begin(); it != list.end(); ++it )
390 {
391 // Each file has a group ed:
392 TQString Group="Cache "+ *it;
393
394 // Let's go to this group
395 config.setGroup(Group);
396
397 // stat the file
398 struct stat sbuf;
399 memset (&sbuf, 0, sizeof(sbuf));
400 stat(TQFile::encodeName(*it), &sbuf);
401 kdDebug()<<"Lua script file:"<<(*it)<<endl;
402 // If the group exist and we're not forced to read the .js file, let's build myModeList for katepartjscriptrc
403 bool readnew=false;
404 if (!force && config.hasGroup(Group) && (sbuf.st_mtime == config.readNumEntry("lastModified")))
405 {
406 config.setGroup(Group);
407 TQString filePath=*it;
408 TQString internalName=config.readEntry("internlName","KATE-ERROR");
409 if (internalName=="KATE-ERROR") readnew=true;
410 else
411 {
412 TQString niceName=config.readEntry("niceName",internalName);
413 TQString copyright=config.readEntry("copyright",i18n("(Unknown)"));
414 double version=config.readDoubleNumEntry("version",0.0);
415 KateLUAIndentScriptImpl *s=new KateLUAIndentScriptImpl(
416 internalName,filePath,niceName,copyright,version);
417 m_scripts.insert (internalName, s);
418 }
419 }
420 else readnew=true;
421 if (readnew)
422 {
423 TQFileInfo fi (*it);
424
425 if (m_scripts[fi.baseName()])
426 continue;
427
428 TQString internalName=fi.baseName();
429 TQString filePath=*it;
430 TQString niceName=internalName;
431 TQString copyright=i18n("(Unknown)");
432 double version=0.0;
433 parseScriptHeader(filePath,&niceName,&copyright,&version);
434 /*save the information for retrieval*/
435 config.setGroup(Group);
436 config.writeEntry("lastModified",sbuf.st_mtime);
437 config.writeEntry("internalName",internalName);
438 config.writeEntry("niceName",niceName);
439 config.writeEntry("copyright",copyright);
440 config.writeEntry("version",version);
441 KateLUAIndentScriptImpl *s=new KateLUAIndentScriptImpl(
442 internalName,filePath,niceName,copyright,version);
443 m_scripts.insert (internalName, s);
444 }
445 }
446
447 // Syncronize with the file katepartjscriptrc
448 config.sync();
449}
450
451KateIndentScript KateLUAIndentScriptManager::script(const TQString &scriptname) {
452 KateLUAIndentScriptImpl *s=m_scripts[scriptname];
453 kdDebug(13050)<<scriptname<<"=="<<s<<endl;
454 return KateIndentScript(s);
455}
456
457void KateLUAIndentScriptManager::parseScriptHeader(const TQString &filePath,
458 TQString *niceName,TQString *copyright,double *version)
459{
460#if 0
461 TQFile f(TQFile::encodeName(filePath));
462 if (!f.open(IO_ReadOnly) ) {
463 kdDebug(13050)<<"Header could not be parsed, because file could not be opened"<<endl;
464 return;
465 }
466 TQTextStream st(&f);
467 st.setEncoding (TQTextStream::UnicodeUTF8);
468 if (!st.readLine().upper().startsWith("/**KATE")) {
469 kdDebug(13050)<<"No header found"<<endl;
470 f.close();
471 return;
472 }
473 // here the real parsing begins
474 kdDebug(13050)<<"Parsing indent script header"<<endl;
475 enum {NOTHING=0,COPYRIGHT=1} currentState=NOTHING;
476 TQString line;
477 TQString tmpblockdata="";
478 TQRegExp endExpr("[\\s\\t]*\\*\\*\\/[\\s\\t]*$");
479 TQRegExp keyValue("[\\s\\t]*\\*\\s*(.+):(.*)$");
480 TQRegExp blockContent("[\\s\\t]*\\*(.*)$");
481 while ((line=st.readLine())!=TQString::null) {
482 if (endExpr.exactMatch(line)) {
483 kdDebug(13050)<<"end of config block"<<endl;
484 if (currentState==NOTHING) break;
485 if (currentState==COPYRIGHT) {
486 *copyright=tmpblockdata;
487 break;
488 }
489 Q_ASSERT(0);
490 }
491 if (currentState==NOTHING)
492 {
493 if (keyValue.exactMatch(line)) {
494 TQStringList sl=keyValue.capturedTexts();
495 kdDebug(13050)<<"key:"<<sl[1]<<endl<<"value:"<<sl[2]<<endl;
496 kdDebug(13050)<<"key-length:"<<sl[1].length()<<endl<<"value-length:"<<sl[2].length()<<endl;
497 TQString key=sl[1];
498 TQString value=sl[2];
499 if (key=="NAME") (*niceName)=value.stripWhiteSpace();
500 else if (key=="VERSION") (*version)=value.stripWhiteSpace().toDouble(0);
501 else if (key=="COPYRIGHT")
502 {
503 tmpblockdata="";
504 if (value.stripWhiteSpace().length()>0) tmpblockdata=value;
505 currentState=COPYRIGHT;
506 } else kdDebug(13050)<<"ignoring key"<<endl;
507 }
508 } else {
509 if (blockContent.exactMatch(line))
510 {
511 TQString bl=blockContent.capturedTexts()[1];
512 //kdDebug(13050)<<"block content line:"<<bl<<endl<<bl.length()<<" "<<bl.isEmpty()<<endl;
513 if (bl.isEmpty())
514 {
515 (*copyright)=tmpblockdata;
516 kdDebug(13050)<<"Copyright block:"<<endl<<(*copyright)<<endl;
517 currentState=NOTHING;
518 } else tmpblockdata=tmpblockdata+"\n"+bl;
519 }
520 }
521 }
522 f.close();
523#endif
524}
525//END
526
527#endif
KateDocCursor
Cursor class with a pointer to its document.
Definition: katecursor.h:93
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()
TDEStdAccel::key
int key(StdAccel id)
TDEStdAccel::name
TQString name(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.