- 浏览: 225273 次
- 性别:
- 来自: 北京
-
文章分类
最新评论
-
dysking:
SWT 和 JFace -
wangyuhfut:
东西不少啊。学习中。。。
一个比较好、中文说明的emacs配置文件 1 -
pacocai:
呵呵!学习,学习~~~不过要说编辑器的话个人更喜欢用VIM,比 ...
一个比较好、中文说明的emacs配置文件 1 -
zhf1zhf2:
这两百多个记起来也不容易啊
英国人是这样背的! -
regex:
试了两次,都是乱码,版本是23.1.1,看来不适合
汉化 Emacs 菜单
Syntax Highlight
developerWorks
https://www.ibm.com/developerworks/cn/opensource/os-cn-ecljtf2/
(暂时没有维护图片链接)
样例代码
级别: 中级
马 若劼 (maruojie@cn.ibm.com), 软件工程师, IBM 中国软件开发中心
2008 年 3 月 20 日
Syntax Highlight(语法高亮)是指把文本的不同内容用不同的颜色,字体等渲染,通过这种方式,用户可以快速发现某种内容,可以在短时间内对全文的结构有一个大概的了解。本文探讨如何在 JTF 中实现语法高亮。
Syntax Highlight(语法高亮)是指把文本的不同内容用不同的颜色,字体等渲染,通过这种方式,用户可以快速发现某种内容,可以在短时间内对全文的结构有一个大概的了解。本文探讨如何在 JTF 中实现语法高亮。
前提
语法高亮是把一段文本中的不同内容使用不同的样式来渲染的功能,如下图所示:
图1. Java编辑器的语法高亮
Jav a编辑器的语法高亮
图 1 中的 Java 源代码的不同部分被 Java 编辑器渲染成了不同颜色。比如关键字是偏红的,并且是粗体;变量是蓝色,注释是绿色等等。不同的颜色可以让用户迅速的找到想要的内容,可以说是一个很方便的辅助功能。
在本系列的一部分中,我提到了 ANTLR 以及使用 ANTLR 产生词法和语法分析器。语法高亮是一个很依赖词法分析器的功能,因为词法分析器会把字符流解析成符号流,符号包含了各种属性,比如类型,起始位置和结束位置等等,语法高亮恰恰需要这些信息来渲染文本。我们已经有了一些基础类可以帮助我们管理符号列表,比如 TokenList,它可以根据字符偏移得到对应的符号。这为实现语法高亮提供了良好的基础。
回页首
ITokenScanner
JTF 是通过一个 ITokenScanner 接口来了解符号信息的,我们先来看一看这个接口的定义:
清单 1. ITokenScanner 接口
public interface ITokenScanner {
void setRange(IDocument document, int offset, int length);
IToken nextToken();
int getTokenOffset();
int getTokenLength();
}
可见通过这个接口,JTF 可以遍历所有的符号并且得到符号的偏移和长度信息。所以实现这个接口是一个实质性的工作。但是 JTF 怎么知道如何去渲染不同的文本呢?为了解决这个问题,JTF 也提供了一个 IToken 接口,并且有一个基本的实现类 Token。注意 ANTLR 里面也有 Token 这个类,两者的概念类似,只不过用法不同。JTF 的 Token 可以附带一些自定义的对象,我们可以把文本的属性,比如前景背景字体样式等等,都放到 Token 里面,这样 JTF 就知道该如何渲染文本了。这些文本属性也被 JTF 包装成了一个 TextAttribute 类,我们在构造 Token 之后的传入 TextAttribute 对象就可以了。
既然我们有了 TokenList 这样的基础类,实现 ITokenScanner 就是很简单的事了,我们看看 ExprTokenScanner 的代码:
清单 2. ExprTokenScanner 实现了 ITokenScanner
public class ExprTokenScanner implements ITokenScanner {
/*
* JFace token type definition
*/
private static IToken VARIABLE = new Token(
new TextAttribute(ColorManager.getInstance().getColor(IColorConstants.VARIABLE)));
private static IToken INTEGER = new Token(
new TextAttribute(ColorManager.getInstance().getColor(IColorConstants.INTEGER)));
private static IToken DEFAULT = new Token(
new TextAttribute(ColorManager.getInstance().getColor(IColorConstants.DEFAULT)));
// character offset
private int offset;
// last token returned by nextToken()
private CommonToken lastToken;
// token list
private TokenList tokenList;
public ExprTokenScanner() {
offset = 0;
}
public int getTokenLength() {
return lastToken.getStopIndex() - lastToken.getStartIndex() + 1;
}
public int getTokenOffset() {
return lastToken.getStartIndex();
}
public IToken nextToken() {
if(lastToken == null)
lastToken = tokenList.getToken(offset);
else
lastToken = tokenList.getNextToken(lastToken);
if(lastToken == null)
return Token.UNDEFINED;
switch(lastToken.getType()) {
case IExprTokens.ID:
return VARIABLE;
case IExprTokens.INT:
return INTEGER;
case org.antlr.runtime.Token.EOF:
return Token.EOF;
default:
return DEFAULT;
}
}
public void setRange(IDocument document, int offset, int length) {
lastToken = null;
this.offset = offset;
tokenList = TokenManager.getTokenList(document);
}
}
getTokenLength 和 getTokenOffset 的实现是相当直接的,因为长度和偏移信息都保存在了 ANTLR 的 Token 实现中。nextToken 稍微有点长,因为我们需要把 ANTLR 的 Token 映射到 JTF 的 Token,所有用了一个 swtich 语句来检查了一下 Token 的类型,从而返回相应的 JTF Token。返回的 Token 已经预先定义好了,并加上了文本属性信息。setRange 可能是个不太直观的方法,这个方法有两个目的:第一是将 ITokenScanner 和 IDocument 分离开,这样一个 ITokenScanner 可以为多个 IDocument 服务;第二是提高性能,因为每次都从头把文本渲染一遍是个不太经济的做法,所以 setRange 有 offset 和 length 两个参数来控制需要渲染的范围,提高了渲染速度。
回页首
PresentationReconciler
有了 TokenScanner 之后,剩下的事情就是让 JTF 知道它。上一部分提到了 SourceViewerConfiguration,它是 JTF 和外界交互的枢纽。我已经实现了 ExprConfiguation,但是它还是空的,现在我们就要覆盖父类的 getPresentationReconciler 方法:
清单 3. 覆盖父类的 getPresentationReconciler 方法
public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer)
{
PresentationReconciler reconciler = new PresentationReconciler();
DefaultDamagerRepairer dr = new DefaultDamagerRepairer(getTokenScanner());
reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
return reconciler;
}
PresentationReconciler,顾名思义,是一个负责 Presentation 的类,这里 Presentation 指的就是文本的颜色,字体等等。文本渲染是一个不断进行的过程,因为用户可能在不断的修改文本内容。JTF 必须知道用户输入了什么,然后重新检查一下输入的内容,再刷新。所以 JTF 引入了 Damager 和 Repairer 的概念,Damager 负责计算用户的输入对哪些区域造成了破坏,Repairer 负责重新渲染被破坏的文本区域。Damager 和 Repairer 是按照文本类型来组织的,但是在我们的例子中,只有一个缺省文本类型,所以我们只为缺省类型设置了 Damager 和 Repairer。稍后我们会简单介绍一下文本类型的概念。
提示:ExprConfiguration 已经在 JTFDialog 中和 ExprViewer 联系起来了,具体参见 JTFDialog的createDialogArea 方法。
幸运的是 JTF 已经为我们提供了 PresentationReconciler 以及 Damager,Repairer 的缺省实现,很少有需要扩展这些类的情况。这里我就不详细解释了。
回页首
Content Type
你可以把 Content Type 翻译成文本类型后者内容类型,总之它是用来描述具有某种特征的文字的。比如在 XML 语言中,标签肯定是由大于号和小于号括起来的,这样你就可以给 XML 的标签定义一种文本类型,更细一点,XML 的结束标签是由 "</" 和 ">" 括起来的,所以也可以为结束标签定义一种单独的文本类型。上一小节提到了不同的文本类型可以有不同的 Damager 和 Repairer,实际上 JTF 中很多特性都可以针对某个文本类型来做,因此适当的使用文本类型可以做一些更精细的控制。不过,这也得根据你要编辑的文本来具体考虑,像 XML 这样的非常结构化的语言,划分文本类型是很容易的。但是对于我这个例子中的数学表达式语言来说,就不太方便划分出很多类型来,你非要划分一下,可能会使得简单问题复杂化了。所以,要具体问题具体分析。
另外一个问题是 JTF 如何知道某段文本是什么样的类型呢?这里需要引入一个 Partition(分区)的概念,在 JTF 中,每个文档都有一个与之联系的 Document Partitioner(文档分区器),它会根据你给定的规则来扫描整个文本从而辨别哪块是哪个类型。所以它有一个相同的问题:对于非结构化的语言,划分分区不是特别容易的事情。
提示:关于分区和扫描规则的内容,读者可以参考 IDocumentPartitioner 和 IRule 接口以及它们的实现。这里不做详细的解释了。
所以当你要处理一种文法规则不那么严谨的语言的时候,也可以不定义文本类型,就用缺省的就够了。我的例子就都采用了这样的方式。同时由于 ANTLR 生成的词法分析器非常好用,所以也没有必要那么做。
回页首
结束语
语法高亮的部分到这里就完成了,下图是例子的效果:
图 1. 语法高亮效果图
语法高亮效果图
变量的颜色是咖啡色,数字是蓝色,其它都缺省是黑色。有了语法高亮的帮助,整个文档结构都一目了然了。
回页首
声明
本文仅代表作者的个人观点,不代表 IBM 的立场。
developerWorks
https://www.ibm.com/developerworks/cn/opensource/os-cn-ecljtf2/
(暂时没有维护图片链接)
样例代码
级别: 中级
马 若劼 (maruojie@cn.ibm.com), 软件工程师, IBM 中国软件开发中心
2008 年 3 月 20 日
Syntax Highlight(语法高亮)是指把文本的不同内容用不同的颜色,字体等渲染,通过这种方式,用户可以快速发现某种内容,可以在短时间内对全文的结构有一个大概的了解。本文探讨如何在 JTF 中实现语法高亮。
Syntax Highlight(语法高亮)是指把文本的不同内容用不同的颜色,字体等渲染,通过这种方式,用户可以快速发现某种内容,可以在短时间内对全文的结构有一个大概的了解。本文探讨如何在 JTF 中实现语法高亮。
前提
语法高亮是把一段文本中的不同内容使用不同的样式来渲染的功能,如下图所示:
图1. Java编辑器的语法高亮
Jav a编辑器的语法高亮
图 1 中的 Java 源代码的不同部分被 Java 编辑器渲染成了不同颜色。比如关键字是偏红的,并且是粗体;变量是蓝色,注释是绿色等等。不同的颜色可以让用户迅速的找到想要的内容,可以说是一个很方便的辅助功能。
在本系列的一部分中,我提到了 ANTLR 以及使用 ANTLR 产生词法和语法分析器。语法高亮是一个很依赖词法分析器的功能,因为词法分析器会把字符流解析成符号流,符号包含了各种属性,比如类型,起始位置和结束位置等等,语法高亮恰恰需要这些信息来渲染文本。我们已经有了一些基础类可以帮助我们管理符号列表,比如 TokenList,它可以根据字符偏移得到对应的符号。这为实现语法高亮提供了良好的基础。
回页首
ITokenScanner
JTF 是通过一个 ITokenScanner 接口来了解符号信息的,我们先来看一看这个接口的定义:
清单 1. ITokenScanner 接口
public interface ITokenScanner {
void setRange(IDocument document, int offset, int length);
IToken nextToken();
int getTokenOffset();
int getTokenLength();
}
可见通过这个接口,JTF 可以遍历所有的符号并且得到符号的偏移和长度信息。所以实现这个接口是一个实质性的工作。但是 JTF 怎么知道如何去渲染不同的文本呢?为了解决这个问题,JTF 也提供了一个 IToken 接口,并且有一个基本的实现类 Token。注意 ANTLR 里面也有 Token 这个类,两者的概念类似,只不过用法不同。JTF 的 Token 可以附带一些自定义的对象,我们可以把文本的属性,比如前景背景字体样式等等,都放到 Token 里面,这样 JTF 就知道该如何渲染文本了。这些文本属性也被 JTF 包装成了一个 TextAttribute 类,我们在构造 Token 之后的传入 TextAttribute 对象就可以了。
既然我们有了 TokenList 这样的基础类,实现 ITokenScanner 就是很简单的事了,我们看看 ExprTokenScanner 的代码:
清单 2. ExprTokenScanner 实现了 ITokenScanner
public class ExprTokenScanner implements ITokenScanner {
/*
* JFace token type definition
*/
private static IToken VARIABLE = new Token(
new TextAttribute(ColorManager.getInstance().getColor(IColorConstants.VARIABLE)));
private static IToken INTEGER = new Token(
new TextAttribute(ColorManager.getInstance().getColor(IColorConstants.INTEGER)));
private static IToken DEFAULT = new Token(
new TextAttribute(ColorManager.getInstance().getColor(IColorConstants.DEFAULT)));
// character offset
private int offset;
// last token returned by nextToken()
private CommonToken lastToken;
// token list
private TokenList tokenList;
public ExprTokenScanner() {
offset = 0;
}
public int getTokenLength() {
return lastToken.getStopIndex() - lastToken.getStartIndex() + 1;
}
public int getTokenOffset() {
return lastToken.getStartIndex();
}
public IToken nextToken() {
if(lastToken == null)
lastToken = tokenList.getToken(offset);
else
lastToken = tokenList.getNextToken(lastToken);
if(lastToken == null)
return Token.UNDEFINED;
switch(lastToken.getType()) {
case IExprTokens.ID:
return VARIABLE;
case IExprTokens.INT:
return INTEGER;
case org.antlr.runtime.Token.EOF:
return Token.EOF;
default:
return DEFAULT;
}
}
public void setRange(IDocument document, int offset, int length) {
lastToken = null;
this.offset = offset;
tokenList = TokenManager.getTokenList(document);
}
}
getTokenLength 和 getTokenOffset 的实现是相当直接的,因为长度和偏移信息都保存在了 ANTLR 的 Token 实现中。nextToken 稍微有点长,因为我们需要把 ANTLR 的 Token 映射到 JTF 的 Token,所有用了一个 swtich 语句来检查了一下 Token 的类型,从而返回相应的 JTF Token。返回的 Token 已经预先定义好了,并加上了文本属性信息。setRange 可能是个不太直观的方法,这个方法有两个目的:第一是将 ITokenScanner 和 IDocument 分离开,这样一个 ITokenScanner 可以为多个 IDocument 服务;第二是提高性能,因为每次都从头把文本渲染一遍是个不太经济的做法,所以 setRange 有 offset 和 length 两个参数来控制需要渲染的范围,提高了渲染速度。
回页首
PresentationReconciler
有了 TokenScanner 之后,剩下的事情就是让 JTF 知道它。上一部分提到了 SourceViewerConfiguration,它是 JTF 和外界交互的枢纽。我已经实现了 ExprConfiguation,但是它还是空的,现在我们就要覆盖父类的 getPresentationReconciler 方法:
清单 3. 覆盖父类的 getPresentationReconciler 方法
public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer)
{
PresentationReconciler reconciler = new PresentationReconciler();
DefaultDamagerRepairer dr = new DefaultDamagerRepairer(getTokenScanner());
reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);
reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);
return reconciler;
}
PresentationReconciler,顾名思义,是一个负责 Presentation 的类,这里 Presentation 指的就是文本的颜色,字体等等。文本渲染是一个不断进行的过程,因为用户可能在不断的修改文本内容。JTF 必须知道用户输入了什么,然后重新检查一下输入的内容,再刷新。所以 JTF 引入了 Damager 和 Repairer 的概念,Damager 负责计算用户的输入对哪些区域造成了破坏,Repairer 负责重新渲染被破坏的文本区域。Damager 和 Repairer 是按照文本类型来组织的,但是在我们的例子中,只有一个缺省文本类型,所以我们只为缺省类型设置了 Damager 和 Repairer。稍后我们会简单介绍一下文本类型的概念。
提示:ExprConfiguration 已经在 JTFDialog 中和 ExprViewer 联系起来了,具体参见 JTFDialog的createDialogArea 方法。
幸运的是 JTF 已经为我们提供了 PresentationReconciler 以及 Damager,Repairer 的缺省实现,很少有需要扩展这些类的情况。这里我就不详细解释了。
回页首
Content Type
你可以把 Content Type 翻译成文本类型后者内容类型,总之它是用来描述具有某种特征的文字的。比如在 XML 语言中,标签肯定是由大于号和小于号括起来的,这样你就可以给 XML 的标签定义一种文本类型,更细一点,XML 的结束标签是由 "</" 和 ">" 括起来的,所以也可以为结束标签定义一种单独的文本类型。上一小节提到了不同的文本类型可以有不同的 Damager 和 Repairer,实际上 JTF 中很多特性都可以针对某个文本类型来做,因此适当的使用文本类型可以做一些更精细的控制。不过,这也得根据你要编辑的文本来具体考虑,像 XML 这样的非常结构化的语言,划分文本类型是很容易的。但是对于我这个例子中的数学表达式语言来说,就不太方便划分出很多类型来,你非要划分一下,可能会使得简单问题复杂化了。所以,要具体问题具体分析。
另外一个问题是 JTF 如何知道某段文本是什么样的类型呢?这里需要引入一个 Partition(分区)的概念,在 JTF 中,每个文档都有一个与之联系的 Document Partitioner(文档分区器),它会根据你给定的规则来扫描整个文本从而辨别哪块是哪个类型。所以它有一个相同的问题:对于非结构化的语言,划分分区不是特别容易的事情。
提示:关于分区和扫描规则的内容,读者可以参考 IDocumentPartitioner 和 IRule 接口以及它们的实现。这里不做详细的解释了。
所以当你要处理一种文法规则不那么严谨的语言的时候,也可以不定义文本类型,就用缺省的就够了。我的例子就都采用了这样的方式。同时由于 ANTLR 生成的词法分析器非常好用,所以也没有必要那么做。
回页首
结束语
语法高亮的部分到这里就完成了,下图是例子的效果:
图 1. 语法高亮效果图
语法高亮效果图
变量的颜色是咖啡色,数字是蓝色,其它都缺省是黑色。有了语法高亮的帮助,整个文档结构都一目了然了。
回页首
声明
本文仅代表作者的个人观点,不代表 IBM 的立场。
发表评论
-
基于 JFace Text Framework 构建全功能代码编辑器: 第 7 部分:
2009-05-17 16:18 1105https://www.ibm.com/developerwo ... -
基于 JFace Text Framework 构建全功能代码编辑器: 第 6 部分:Text Ho
2009-05-17 16:17 1336https://www.ibm.com/developerwo ... -
基于 JFace Text Framework 构建全功能代码编辑器: 第 5 部分:
2009-05-14 17:32 1277https://www.ibm.com/developerwo ... -
基于 JFace Text Framework 构建全功能代码编辑器: 第 4 部分
2009-05-14 17:31 1571Content Assistant developerWor ... -
基于 JFace Text Framework 构建全功能代码编辑器: 第 3 部分
2009-05-14 17:30 1351Double Click 和 Triple Click de ... -
实战SWT布局
2008-12-08 00:55 1448标准的SWT布局类 FillLayou ... -
SWT布局
2008-12-08 00:53 1197另外参见:http://java.chinaitlab.com ... -
基于 JFace Text Framework 构建全功能代码编辑器: 第 1 部分
2008-11-19 18:11 1237级别: 中级 马 若劼 (maruojie@cn.ibm.c ... -
SWT 和 JFace, 第 2 部分: 简介
2008-11-19 18:06 1210http://www.ibm.com/developerwor ... -
SWT 和 JFace,第 1 部分: 简介
2008-11-19 18:04 1215http://www.ibm.com/developerwor ... -
基于 JFace Text Framework 构建全功能代码编辑器: 第 8 部分:
2008-11-19 03:54 0https://www.ibm.com/developerwo ... -
基于 JFace Text Framework 构建全功能代码编辑器: 第 10 部分:Text F
2008-11-19 03:50 0https://www.ibm.com/developerwo ... -
基于 JFace Text Framework 构建全功能代码编辑器: 第 11 部分:
2008-11-19 03:48 0https://www.ibm.com/developerwo ... -
基于 JFace Text Framework 构建全功能代码编辑器: 第 9 部分:Templa
2008-11-19 03:23 0基于 JFace Text Framework 构 ... -
JFace Text Editor完全掌握之终极指南
2008-06-13 01:57 1944JFace Text Editor是JFace里面一个功能强大 ... -
JFace 视图
2008-06-13 01:49 1198http://blog.itpub.net/post/5050 ... -
SWT的体系结构
2008-06-13 01:18 1268http://flyingbug.blogdriver.com ... -
SWT 全接触
2008-06-13 01:15 1828http://blog.csdn.net/DL88250/ar ... -
细说:AWT,SWT,Swing
2008-06-13 00:42 2104http://www.java3z.com/cwbwebhom ... -
SWT的--键盘事件处理
2008-06-12 21:51 2392http://203.208.37.104/search?q= ...
相关推荐
### 基于_JFace_Text_Framework_构建全功能代码编辑器 #### 引言与概述 _JFace_Text_Framework_(简称JTF),作为Eclipse平台的重要组成部分,为开发者提供了构建高度定制化的代码编辑器的强大能力。JTF不仅支撑了...
- 利用RCP架构组织应用的各个部分,如工作台视图、编辑器、透视图等。 - 调试和测试Eclipse插件,确保其在不同环境下正常运行。 通过深入研究这些实例代码,开发者不仅可以提升Eclipse插件开发技能,还能了解到如何...
3. **代码编辑器**:Eclipse的代码编辑器提供了丰富的代码提示、自动完成、语法高亮、错误检查等功能,极大地提高了开发效率。 4. **构建工具(Builder)**:Eclipse内置了Java编译器,可以自动检测源代码变化并...
4. **透视图(Perspectives)、视图(Views)、编辑器(Editors)和操作(Actions)**:这些是Eclipse插件开发中的基本元素,它们构成了用户界面的主要部分。学习如何创建和定制这些组件以提供特定功能。 5. **调试...
【EMF(Eclipse Modeling Framework)2.2.0】:EMF是Eclipse的一个重要组成部分,它基于 OMG 的 MOF(Meta-Object Facility)标准,提供了创建、存储和操作模型的强大工具。2.2.0版本可能引入了对模型版本控制的支持...
这份"eclipsePluginStudyNoteSourceCode"压缩包提供了从第1章到第24章的Eclipse插件开发学习笔记源代码,涵盖了从基础到进阶的全方面知识。 在Eclipse插件开发中,你需要了解以下核心概念: 1. **插件体系结构**:...
首先,书中会介绍Eclipse RCP的基础知识,包括工作台(Workbench)、视图(Views)、编辑器(Editors)、透视图(Perspectives)等核心概念。这些元素构成了Eclipse RCP应用的基本结构,理解它们对于后续的开发至关...
RCP是Eclipse框架的一个重要组成部分,它允许开发者构建功能丰富的桌面应用程序,具有与IDE类似的用户体验。 书中主要涵盖了以下几个关键知识点: 1. **Eclipse RCP基础**:介绍Eclipse RCP的基本概念,包括其架构...
在《Eclipse插件开发 学习笔记 第3篇 高级进阶》中,开发者将会学习到更多高级主题,比如命令框架(Command Framework)、透视图(Perspectives)、视图(Views)、编辑器(Editors)和操作(Actions)。这些是构建...