当前项目进展及小结
到昨天为止,基本完成Code Snippet的框架,剩下的都是些体力活。该特性要求在点击菜单项时,根据当前光标所在位置的字符串,替换成对应的代码片段。由于菜单项是通过插件添加实现的,而且Code Snippet又根据当前编辑的源代码对应的编程语言不同,也会有不同的处理,所以也是通过不同的插件实现的,这就要求插件可以再次调用插件。好在当初设计插件扩展框架时,已经考虑到这一点,所以虽然有实现过程中有需要慢慢调试的地方,但没有特别大的障碍。
完成Code Snippet后,应该开始Auto Completion特性的开发。该特性是本项目中可算是难度最高的特性之一,同时又有比较高的准确性和运行效率等要求。还有点比较头痛的是,针对不同的编程语言,可复用的东西不多。
此外,还有个功能应该尽早加入,就是处理文件的不同编码。比如通常,尤其是早期的代码,都是直接使用ANSI编码保存。而现在已经比较常用的是保存成UTF-8等编码方式,特别是像LaTeX的一些处理器直接要求输入文件是UTF-8编码。所以应该能在文件的装入和保存时,可以自动处理文件的编码问题,这可以通过iconv或ICU实现,不过问题就在于有了选择,才是苦恼啊!目前我倾向于使用iconv,因为相比之下更轻量,而且够用。
这些天发现,Lua的字符串连接符..效率还真低,怪不得Lua要提供*all和table.concat等设施。
本来Lua中操作XML有几种不同的选择,这跟在C++中情况差不多,我选择的是比较轻量的ltxml。而昨天在Code Snippet特性的开发过程中发现,我把所有的信息都保存在xml中,而每次完成snippet时都从xml中读取,开始几次还是正常的,但只要过一会儿,在调用xml.open时就会报什么试图index一个function值中一个number值,还真是诡异,但调试发现这时无论xml.open还是传入的参数都是正确的,很是纳闷啊。于是只好规避一下,只在开始时读一次,全部都装入到内存中,以后就直接读内存了。
一直以来,都是通过print来进行Lua脚本调试,真是应了那句“一夜回到解放前”。前两天才在界面上加了一个专门的输出窗口用于从Lua脚本打印字符串过来。好比是当年写Windows GUI程序时,用MessageBox调试进化到用OutputDebugStrng进行调试。昨天记起来有LuaLogging这么个第三方库,于是仔细看了看,很简单的功能,只有几个lua文件,可以记录日志到文件、控制台、socket、email或数据库中。于是我参照这些appender的实现,加了一个新的appender,用于将日志打印到宿主的插件输出窗口中,感觉不错。
接着是使用luabind的问题。在网上看到有人说luabind的各个版本都存在指针的double deleting问题,这让我有点惶恐。好在今天看邮件列表时,看到luabind的作者说,这种问题只出现在使用智能指针或类继承时切片的情况,而且要求是Lua的state先于这些对象被销毁,现在没有好的办法来修正这个问题。我想了想,这几种情况我现在都不会遇到,我只有最最简单的嵌入和扩展交互。之后,又发现有人在邮件列表中写了一个luabind和SWIG的性能比较,SWIG的封装比luabind的快一倍。看到这个结果,我觉得是意料之中,SWIG的封装方式比较底层,调用快也是正常的。不过luabind的作者说,他写了些benchmark的测试,在未发布的luabind 0.9中已经有不小的改进,虽然仍然不比SWIG快,但相比0.8.1版本,差距缩小了约一半,期待0.9的发布。
昨天无意中看到云风blog上一篇老文章提到有Lua Ring这么个库,可以在Lua代码中再创建个新的Lua state,让某些代码在这个新的state中运行,从而保护比较重要的核心state。我潜意识中认为,像我现在这个项目使用嵌入Lua来作为插件扩展的运行环境,确实要用一个比较安全的环境,即所谓的沙盒,但这个Lua Ring怎么应用上去,以及能有多少效果,仍然有待考察。
前些天,从SVN上更新的了wxPropertyGrid的代码后,发现用GCC编译不过了,直到昨天仍然不行,实在忍无可忍,真要骂娘了。上它的sf项目见面看了一下,自11月25日更新代码后,估计作者就压根没发现这个问题,于是在上面提了个单。今天发现作者已经回复那个单,并在svn trunk中已经修正了该问题,总算松了口气。
今天仔细学了一下如何让wxWidgets支持国际化,发现非常简单。只要在程序初始化时,自己创建一个wxLocale对象,把mo文件的搜索路径加进去,设置好当前要使用的语言。其他想要被翻译的字符串用_()宏替换wxT()和_T(),如果是个wxString对象,就用wxGetTranslation(),这样在这些字符串会自动从mo文件中读出相应的翻译后的文本,感觉比ini等配置文件,或是国际化资源dll的方案方便很多。不过为了让插件支持国际化,也可以使用类似的方案,但是我有poEdit时发现它只能从源代码中提取出需要翻译的字符串,不能全新的创建一个,这太土了,以后一定要自己写个好用的。
最后的一个问题是,现在的插件扩展机制,容易出现重复代码,比如相同的功能会在菜单中写一遍,在工具栏中也写一遍,这该怎么修改一下呢,呃,得仔细考虑考虑