`
hqs7636
  • 浏览: 220344 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

基于 JFace Text Framework 构建全功能代码编辑器: 第 2 部分

阅读更多
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 的立场。
分享到:
评论

相关推荐

    基于_JFace_Text_Framework_构建全功能代码编辑器

    ### 基于_JFace_Text_Framework_构建全功能代码编辑器 #### 引言与概述 _JFace_Text_Framework_(简称JTF),作为Eclipse平台的重要组成部分,为开发者提供了构建高度定制化的代码编辑器的强大能力。JTF不仅支撑了...

    JFace Text Framework教程

    总结来说,IBM的JFace Text Framework教程为开发者提供了一个强大且灵活的工具,用于构建功能丰富的文本编辑器。通过学习和实践,开发者可以掌握如何利用这个框架来提升开发效率,创建出专业级的IDE(集成开发环境)...

    eclipse与MyEclipse代码提示上屏修改后jar包(org.eclipse.jface.text_3.8.101.v20130802-1147)

    标题提及的"org.eclipse.jface.text_3.8.101.v20130802-1147"是Eclipse中的一个关键组件,它负责文本编辑器的相关功能,包括代码提示。 `org.eclipse.jface.text`是Eclipse JFace库的一部分,JFace是构建用户界面的...

    jface.text 3.12.1.zip

    本文将围绕"jface.text 3.12.1.zip"这一特定的Eclipse插件进行深入探讨,该插件是Eclipse文本编辑器的重要组成部分,对于提升Java代码补全体验有着至关重要的作用。 首先,"jface.text"是Eclipse的Java Face (JFace...

    org.eclipse.jface.text_3.12.2.v20180112-1341.zip

    标题中的"org.eclipse.jface.text_3.12.2.v20180112-1341.zip"是Eclipse插件的一个版本,它专注于文本编辑功能。Eclipse是一个开源的集成开发环境(IDE),而JFace是Eclipse的一部分,提供了面向用户的界面组件。...

    org.eclipse.jface.text_3.11.2.v20170220-1911最新修改版

    JFace Text是Eclipse中的一个API,它是构建文本编辑器的基础,提供了文本编辑、搜索、替换、高亮等基本功能。在这个特定的版本中,开发者们对JFace Text进行了优化,特别是对于用户输入行为的处理,比如取消了空格和...

    org.eclipse.jface.text_3.12.2.v20180112-1341.jar

    Eclipse JFace Text是Eclipse IDE中的一个核心组件,它提供了高级文本编辑功能,广泛用于构建用户界面中的文本编辑器。这个特定的版本号表明它是该组件的一次更新迭代,可能包含错误修复、性能提升或其他新特性。 ...

    基于WTP开发自定义的JSP编辑器

    了解和利用WTP中与插件开发相关的其他关键概念,如JFace Text Framework和Eclipse Editor Framework,可以帮助进一步优化编辑器的性能和用户体验。 #### 五、总结 基于WTP开发自定义的JSP编辑器是一个综合性的工程...

    org.eclipse.jface.text_3.8.2.v20121126-164145源码

    深入研究这部分源码,不仅可以提升对Eclipse JFace的理解,也有助于提升开发者在构建文本编辑器组件时的定制能力。同时,这也提醒我们,源码的修改应遵循良好的编程实践,确保软件的稳定性和可维护性。

    org.eclipse.jface.text_3.7.2.v20111213-1208.jar

    《Eclipse JFace Text库与MyEclipse 10.0.0的编辑器功能优化》 在IT行业中,开发工具的效率与便利性对于程序员的工作至关重要。Eclipse作为一款广受欢迎的开源集成开发环境(IDE),其强大的扩展性和自定义能力一直...

    org.eclipse.jface.text_3.9.2.v20141003-1326.zip

    这个插件是JFace Text组件的一部分,JFace是Eclipse工作台(Workbench)框架的一个子项目,它提供了基于SWT(Standard Widget Toolkit)的高级用户界面构建工具。版本号"3.9.2"表明这是该插件的第三个主要版本的第九...

    Eclipse SWT/JFace 核心应用的全部源代码

    JFace包括数据绑定、视图管理、对话框和服务等组件,它将许多复杂的SWT操作进行了封装,例如表格和树的数据模型、表单编辑器等。通过研究JFace的源代码,开发者可以学习到如何优雅地组织用户界面,提高代码的可读性...

    org.eclipse.jface.text_3.14.0.v20180824-1140

    org.eclipse.jface.text_3.14.0.v20180824-1140,最新版Eclipse代码上屏jar包,修改了代码上屏按键,取消空格上屏,不会使用的小伙伴请百度Eclipse代码上屏优化!

    MyEclipse10.7.1代码补全vs风格 jface.text修正版

    因为10.7.1已经完美破解(修正了war文件到处问题),故放上该版本修改过的org.eclipse.jface.text_3.7.2.v20111213-1208.jar 代码补全空格不上屏,适合习惯使用vs等工具的用户 详细描述参见10.0时的插件 ...

    jface源代码不容错过

    7. **视图和编辑器的实现**:Eclipse RCP中的视图和编辑器是通过JFace实现的,源代码能帮助我们理解这两者如何在RCP环境中协同工作。 总之,研究JFace的源代码不仅可以帮助开发者深入理解Eclipse RCP的工作原理,还...

    JFace教程

    **JFace** 是 Eclipse 平台的一个重要组成部分,它提供了一套丰富的 API 来帮助开发者构建基于 SWT(Standard Widget Toolkit)的用户界面。JFace 的核心目标是简化 GUI 开发流程,使开发者能够更加专注于应用程序...

    Eclipse SWT/JFACE 核心应用 配套源代码

    2. **JFace**:JFace是在SWT基础上构建的一个高级UI框架,它简化了SWT的使用,提供了数据绑定、对话框、视图管理等功能。JFace的目的是减少代码量,提高代码的可读性和可维护性。源代码中可能包含JFace的使用示例,...

    Eclipse SWT&JFace开发实战精解 源代码

    Eclipse SWT(Standard Widget Toolkit)和JFace是Java编程中用于构建桌面应用程序的两个关键库。它们都是Eclipse IDE的一部分,提供了丰富的用户界面组件和高级的UI设计工具。本篇文章将深入探讨这两个库的核心概念...

    SWT,JFACE核心应用源代码,第二部分.rar

    在"SWT,JFACE核心应用源代码,第二部分.rar"这个压缩包中,我们可以预期找到一系列关于SWT和JFace实际应用的源代码示例。这些示例可能涵盖了如何使用SWT创建基本和复杂的用户界面元素,如何利用JFace进行数据绑定,...

    swt JFace的API文档

    7. **Views and Editors**:JFace 提供了用于构建工作台视图和编辑器的框架,支持多窗口和多页编辑环境。 8. **Control Adapters**:这些适配器类可以添加额外的功能,例如在控件上添加右键菜单。 9. **Bindings ...

Global site tag (gtag.js) - Google Analytics