本来这是打算在上周五完成的,结果上周五又开小差搞界面去了,周六周日又跑去魔都了,于是就拖到这周了。今天刚开始的时候还有点惧怕的,怕是实现难点有点高,甚至又冒出过放弃的念头的。后来还是硬着头皮做一点是一点,结果还不错,比想像的要容易一些,已经能达到90%的计划中的程度了,剩下的10%么,从个人感情上还是从策略上,都应该放到后面的版本中实现了。
下面先说一下最终的表现吧。
前一个版本,code snippet使用的展开缩写的快捷键是Ctrl+,,这次把这个快捷键换到Ctrl+;了,那是因为另外又增加了两个操作,这两个操作是正反对应的,于是分别占用了Ctrl+,和Ctrl+.。正常的操作方法是,假设在编辑Lua源代码时,输入for,这时光标停在最后一个字母r的后面,按快捷键Ctrl+,,会自动将for展开为比较完整的for i = 1,10 do…(省略号表示后面还有些内容,这里不影响说明,就不列出来了)并选中for后面的循环变量i。到这步为止,相比上个版本的实现,只是增加了选中循环变量i的这步操作,但也已经方便了用户可以不再手动移动光标位置来修改变量名称。接下了,就是新增的两个占用了快捷键的操作,即Ctrl+,和Ctrl+.,分别是向左或向右跳动选中1和10。也就是说,在这次for展开后,共有3处可能被自动选中,即i、1、10,至于每次选中哪处,可以通过快捷键Ctrl+,和Ctrl+.来修改。这是基于这样的应用场景:在for循环中,基本的循环结构是自动补完了,但实际上循环变量和变量的初始值和终结值是最可能需要根据情况修改的,于是编辑器就可以通过快捷键快速选中这些部分,而不用再通过鼠标或方向键等常规方法移动输入光标进行修改。这就是最终的表现。
接着简单记一下实现的过程。
因为从整个程序的实现架构上的原因,此功能的实现一部分由Lua脚本完成,一部分由C++完成。首先是修改了code snippet的模板,如上例中的for,在模板中的定义是for ${1:i} = ${2:1}, ${3:10} do…(省略号表示后面还有些内容,这里不影响说明,就不列出来了)可以看到有3处用${}包括的内容,这些内容的都用一个冒号分隔,冒号前面是一个编号,冒号后面是最终展开后填入到编辑器中的内容。编号用于按快捷键Ctrl+,和Ctrl+.时进行排序,Ctrl+,则从大到小跳转,Ctrl+.从小大到跳转,初始状态时选中编号为1的部分。在for后展开snippet,是用Lua脚本完成的,那会先从模板配置文件中找到缩写对应的模板,然后将${}部分全都提取出来并替换成冒号后面的部分内容,并根据当前编辑器的插入位置重新计算和修正每个${}的位置信息。这些位置信息用于后面的选中功能。然后把所有这些信息都存入C++实现的编辑器对象中,在C++实现的编辑器类中会有几处事件通知处理。一处是刷新UI时,更新当前光标位置,如果当前光标位置已经不在任何一个${}的范围内,那么本次code snippet展开就算完成任务了。另一处是编辑器内的文本修改,如果有新增或减少文本,那么要修改当前光标所在的${}的长度(这个长度在选中文本时需要用到),并修改该${}位置后面的所有其他${}的起始位置。只有这样,才能在修改了一处${}后,仍能继续正常地在各处${}间来回跳转。好了,基本的思路就是这样了。
题外话,想说一下,在文本处理方面,脚本语言确实比C++要方便一些,比如查找替换${}部分,在Lua中实现的模式匹配就很好用。
Category Archives: Editor,IDE
进展不错
这两天整调试器,经过不怎样的努力,到现在为止,功能上基本算是具备了,不过就是剩下些bug,主要有:
从debuggee发送过来的信息有时候经过XML解析会出错。
从debuggee发送过来的信息,有时候没有调用栈信息。
断点工作不正常。
有时候刚启动debuggee,debuggee就崩溃。
明后天就集中精力修改这些问题了,哈哈!
代码合得有点问题
用了wxScintilla,我一直试图让其中用到的Scintilla代码保持跟官方CVS中的同步。现在发现,还是合得有问题了,功能没合进来,但是光是看代码,我也不知道到底哪里出错了。具体的现象是,现在官方的Scintilla是已经能直接支持多块选择了,昨天试了试我的程序是不行的。不过这个问题暂时倒不要紧,可以放到以后去修改。
看到SciTE开始有实验性的支持使用Lua脚本实现lexer了,不过接口还没有稳定下来。不过我猜这个特性可能不会合到Scintilla里面去,而且即使合进去了,我暂时也没有这个需求。
自从前些天看到TextMate的Bundles的介绍,以及Zen Coding的介绍,心里一直蠢蠢欲动!VS在有VA强大的智能提示的帮助下,或许可以不用这种方式的支持。但对于已经习惯于UNIX使用文化的人来说,这种自动代码生成方式是很符合他们的使用习惯的,而且同时又能极大地提升编码效率。我就开始琢磨着能不能也实现一下。
Zen Coding的效果看来,主要适用于HTML这种从SGML衍生而来的标识语言,这主要是它的语法,以及它的生成代码上的限制,所以如果不是这方面的应用,可以暂时不管它。
而TextMate的Bundles看起来就很让人心动了,以前只是听说过却没有直观地体验过,所以感触不深,前些天看了一些评论和操作视频以及manual,冲击太大了。当然这种机制在Windows平台上命令行工具并不流行,脚本解释器又不默认安装的环境下,可能不如Linux/Unix/Mac上那么突出,但如果能做成对少数几种工具、脚本语言的支持,也是很有诱惑力的。
大概想了下,如果要实现这套机制,要修改一下Scintilla中对Tab和Back Tab的实现。目前Scintilla中的Tab有两种不同的行为,如果选中整行或多行了,则会对选中行进行缩进,其他情况则是插入空格或制表符。在Bundles中或者说Tab Triggers中,Tab又多了两种行为,一个是缩写扩展,如果同时有多个扩展使用相同的缩写,则要显示AutoCompletion下拉框,另一个是缩写扩展后光标自动跳转。所以我的想法是,要在Scintilla原来的两种行为中增加缩写扩展的行为,并在内部保存一个状态,表示缩写扩展后,所有的Tab操作不再进行默认的缩进或插入空格(制表符),而是在这些时候都给个通知,让宿主程序自己处理这个操作。而宿主程序在适合的时候再发个消息给Scintilla重置那个状态,以便Scintilla又退回原来的Tab处理方式。
算了,不说了,先搞定调试器,再来看这个吧!
几个Scintilla/SciTE相关项目
Scintilla和SciTE就不多说了,我接触到它并真正用到它,有3年多了,一直跟踪着它的最新发展。发现有几个跟它相关的项目,比如有用(有趣),值得记一下。
第一个要说的是SciTE-ru。这是个SciTE的增强版,大概作者是俄罗斯人吧,所以后面加个ru。SciTE从它本身的定位出发,并不会增加很多强悍的辅助功能,只能说是Scintilla有什么能力,SciTE便有什么功能。而SciTE-ru的出现则试图从第三方增强SciTE的不足之处,并修正了一些在Scintilla或SciTE中存在的小缺陷。如果对SciTE有爱,那么SciTe-ru则会让人觉得更有爱。遗憾的是我不在此列。
接着要说的是SciTE LaTeX IDE。这个项目在SciTE-ru的基础上发展而来,但它的定位是成为一个好用的LaTeX编辑器。作者不但在SciTE在软件包中增加了一些编写LaTeX常用的小工具,还在界面上增加了一批方便的按钮和菜单,更重要的是作者修改了Scintilla官方的LaTeX和asymptote的lexer,却没有合入到官方代码库中去。照作者的说法是修改后的lexer要求太苛刻,会破坏原有的应用程序。我是个LaTeX的初级应用者,确实使用SciTE LaTeX IDE编写过几篇文章,觉得从编辑器的角度出发,已经算是很不错了,但如果定位是IDE,则还是差得远的。
最后要说的是Sicintillua。这是个很有趣的Scintilla/SciTE的fork项目,它移除了所有Scintilla中使用C++编写的lexer,取而代之的是一个叫LexLPeg.cxx的文件,里面定义了两个lexer,分别是null和llpeg。对于各种已有编程语言lex支持都是通过外部的Lua脚本实现,所以用SciLexer原有的标准接口查询和设置的lexer都是llpeg,它又增加了两个接口用于设置直正的lexer。这个fork解决了一直以来就有的Scintilla增加lexer不方便的问题,因为有一拨人觉得,使用C++编写lexer并编译进Scintilla中实在麻烦,确实我也这么觉得,只不过我可以容忍,因为我直到现在都没有自己要添加lexer的需求。我简单地看了一下Scintillua的代码与官方CVS中的代码进行了比较,发现修改的地方不是很多,不过修改了一些接口,我不太喜欢,有可能的话,我要在Scintillua的基础上再出个修改版,能更方便地跟官方代码树进行融合。