• 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 <kstandarddirs.h>
33 
34 #include <tdeconfig.h>
35 #include <tdeglobal.h>
36 #include <tdelocale.h>
37 
38 extern "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
59 static KateDocument *katelua_doc;
60 static Kate::View *katelua_view;
61 //END
62 
63 
64 
65 //BEGIN STATIC BINDING FUNCTIONS
66 typedef struct KATELUA_FUNCTIONS {
67  char *name;
68  lua_CFunction func;
69 } KATELUA_FUNCTIONS;
70 
71 static 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 
83 static 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 
124 static 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 
137 static 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 
150 static 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 
163 static int katelua_view_cursorline(lua_State *L) {
164  lua_pushnumber(L,katelua_view->cursorLine());
165  return 1;
166 }
167 static int katelua_view_cursorcolumn(lua_State *L) {
168  lua_pushnumber(L,katelua_view->cursorColumn());
169  return 1;
170 }
171 static 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 }
177 static int katelua_view_setcursorpositionreal(lua_State *L) {
178  return 0;
179 }
180 
181 static 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 
188 static 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 
196 static 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
215 KateLUAIndentScriptImpl::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 
223 KateLUAIndentScriptImpl::~KateLUAIndentScriptImpl()
224 {
225  deleteInterpreter();
226 }
227 
228 void KateLUAIndentScriptImpl::decRef()
229 {
230  KateIndentScriptImplAbstract::decRef();
231  if (refCount()==0)
232  {
233  deleteInterpreter();
234  }
235 }
236 
237 void KateLUAIndentScriptImpl::deleteInterpreter()
238 {
239  if (m_interpreter)
240  {
241  lua_close(m_interpreter);
242  m_interpreter=0;
243  }
244 }
245 
246 bool 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 
302 bool 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 
325 bool KateLUAIndentScriptImpl::processLine(Kate::View *view, const KateDocCursor &line, TQString &errorMsg )
326 {
327  if (!setupInterpreter(errorMsg)) return false;
328  return true;
329 }
330 
331 bool 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
355 KateLUAIndentScriptManager::KateLUAIndentScriptManager():KateIndentScriptManagerAbstract()
356 {
357  collectScripts();
358 }
359 
360 KateLUAIndentScriptManager::~KateLUAIndentScriptManager ()
361 {
362 }
363 
364 void 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 
451 KateIndentScript KateLUAIndentScriptManager::script(const TQString &scriptname) {
452  KateLUAIndentScriptImpl *s=m_scripts[scriptname];
453  kdDebug(13050)<<scriptname<<"=="<<s<<endl;
454  return KateIndentScript(s);
455 }
456 
457 void 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
TDEConfig
KateDocCursor
Cursor class with a pointer to its document.
Definition: katecursor.h:92
TDEStdAccel::key
int key(StdAccel) KDE_DEPRECATED
Kate::View
The Kate::View text editor interface.
Definition: view.h:42
kdDebug
kdbgstream kdDebug(int area=0)
TDEGlobal::dirs
static TDEStandardDirs * dirs()
tdelocale.h
TDEStandardDirs::findAllResources
TQStringList findAllResources(const char *type, const TQString &filter=TQString::null, bool recursive=false, bool unique=false) const
KDE::version
unsigned int version()
endl
kndbgstream & endl(kndbgstream &s)
TDEStdAccel::name
TQString name(StdAccel id)

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
  •     tdecore
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  • tdeioslave
  •   http
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for kate by doxygen 1.8.8
This website is maintained by Timothy Pearson.