posts - 76,  comments - 621,  trackbacks - 0
编辑器制作之代码折叠

   代码折叠这个功能,我最早是在Dreamweaver里面看到的,具体哪个版本记不清了,好多年了。

当时DW的实现是当你选择文本的时候,在编辑器的左侧,有一个折叠的提示,提示你可以把选中的

文本折叠起来。那个时候觉得这个功能,毫无用处。不过自从VisualStudio2003以来,代码折叠

这个功能几乎成为了程序员的必备。

   的确,在浏览代码的时候,代码折叠可以带来一些好处,让重点凸显在用户的面前,或者可以拉近两块

相隔很远的代码,实现比较。当然,这个也完全可以通过分割视图完成。

   在众多的编辑器当中,我认为单纯就代码折叠而言,目前实现的最好的还是VisualStudio,它

可以根据语言上下文的关系,即语法,进行代码折叠,这是其它编辑器无法企及的。当然,它本身也是

一个重量级的IDE,超出了简单编辑器的范畴。

   本文试图描述代码折叠最基本的思路,没有具体的代码。其实这个功能并不难实现,相反很简单。

难点在于要和编辑器本身很好的结合。

   以下面的C语言为例。
   
1 #include <stdio.h>
2 
3 int main(int argc, char *argv[])
4 {
5     printf("Hello, world\n");
6     
7     return 0;
8 }
9 


   如果对上面的代码进行折叠,应该如何实现呢?聪明的读者,应该马上就会知道了代码折叠的思路了。

对,就是在{和},即两个大括号之间进行折叠。那么如何实现递归折叠呢?这个也很简单,我们只要标记

一个Level,不同的Level之间用不同的图标显示在编辑器左侧,点击的时候根据Level的前后大小关系,

判断是该折叠还是该展开。

   比如下面的代码:
 
 1 #include <stdio.h>
 2 
 3 int main(int argc, char *argv[])
 4 {
 5     {
 6         printf("Hello, world\n");
 7    
 8     }
 9     return 0;
10 }


  在第4行和第5行的时候我们应该显示一个+,5, 6,7,8,9我们应该显示和上下文关联的"|"符号,那么代码

也就很好写了。如下,根据前一行的level设置本行的level:
   
int set_level( int prevLevel, const char* str, int len, void* others ){
    
int retLevel = prevLevel;
    
while! end of str ){
        
if( str has '{' )
            retLevel
++;
        
if( str has '}' )
            retLevel
--;
    }
    
return retLevel;
}

分析完的level要保存在行信息里面.不然就无法绘制+或者-了。

    瞧,如此简单的代码折叠就出来了。

    其实大部分的简单编辑器都是这么多的,比如scintilla。这么做的好处是实现起来非常简单,高效,

而且基本上能满足大部分的需求。另外,上面的函数还有一个参数others,这个可以根据前文已经做过的词法分析,

再做进一步处理,从而实现过滤掉注释或者字符串里面的{和},并且还可以实现对注释的折叠。

    很显然,这种方法也有缺点,就是只能实现类C的这种代码折叠。没有办法,每种语言都有自己的特色,

要想做更好的折叠只有这个办法。比如vb,我们可以在funtion和end function之间折叠,html我们可以在

<body>和</body>之间折叠。不可能写了一个就会万能的。
   
    不过,可以有一种类似万能的效果,就是利用Tab或者空格来折叠。也就是Editplus现在做成的那样。

这个实现起来思路和上面是一模一样的,不再赘述。

ps:下一篇,编辑器之代码自动补全,敬请期待。
posted on 2009-03-07 16:07 megax 阅读(3882) 评论(13)  编辑 收藏 引用

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理