分享
 
 
 

集成Log4j到Eclipse中—《Eclipse IN ACTION》第9章 (3)

王朝java/jsp·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

3、编辑器的语法颜色功能

(1)基本概念

l 首先是定义各种Partition(文档中不重叠的文本),用以区分语法明显不同的部分

l 文档中的每个字符必须属于定义得某个Partition或缺省Partition(IDocument.DEFAULT_CONTENT_TYPE)

l 注释应该属于独立的一种Partition

l 由于log4j.properties中除了注释,每行多是name=value形式,所以分成3种Partition

Ø 注释(以#开始)

Ø Value值(包括=)

Ø 缺省Partition(包括name)

l 需要提供一个Partition扫描器供TextEditor调用,来决定哪些文本属于哪个Partition

l 还需要提供Token扫描器供TextEditor调用

l Token是用来设置颜色的最小文本单元

l 每个Partition需要有唯一的Token扫描器

(2)Partition扫描器

l Partition扫描器通过提供的解析规则(定义Partition)进行解析,将文本区分成不同的Partition

l 本例使用JFace提供的基于规则的扫描器,所以需要在plugin.xml清单编辑器的Dependencies页中添加org.eclipse.jface.text插件

package org.xqtu.log4j.editor;

import org.eclipse.jface.text.IDocument;

import org.eclipse.jface.text.rules.IPredicateRule;

import org.eclipse.jface.text.rules.RuleBasedPartitionScanner;

import org.eclipse.jface.text.rules.SingleLineRule;

import org.eclipse.jface.text.rules.Token;

public class PropertiesPartitionScanner extends RuleBasedPartitionScanner {

public final static String LOG4J_COMMENT = "__log4j_comment";

public final static String LOG4J_VALUE = "__log4j_value";

public PropertiesPartitionScanner() {

super();

Token commentPartition = new Token(LOG4J_COMMENT);

Token valuePartition = new Token(LOG4J_VALUE);

SingleLineRule commentRule = new SingleLineRule("#", null,

commentPartition, (char) 0, true);

commentRule.setColumnConstraint(0);

SingleLineRule valueRule = new SingleLineRule("=", null,

valuePartition, (char) 0, true);

setPredicateRules(new IPredicateRule[] { commentRule, valueRule });

}

public static String[] getLegalContentTypes() {

return new String[] { IDocument.DEFAULT_CONTENT_TYPE,

PropertiesPartitionScanner.LOG4J_COMMENT,

PropertiesPartitionScanner.LOG4J_VALUE };

}

}

l 这里扩展了RuleBasedPartitionScanner,通过读取文本,应用提供的Partition规则

l 在开始部分定义了Partition类型常量

l 在构造方法中定义了每种Partition类型(这里部包括缺省Partition类型)的规则

l 首先创建每种Partition自己唯一的Token对象

l 使用SingleLineRule定义Partition规则,SingleLineRule包括四个参数:

Ø 开始序列匹配模式

Ø 结束序列匹配模式

Ø Escape字符

Ø 设置为true表示当到达文件结束时终止

l setColumnConstraint()方法设置Partition规则的列限制:只返回匹配从指定列数开始的符合规则的Token

l setPredicateRules()方法告诉Partition扫描器定义的Partition规则

l 最后的getLegalContentTypes()方法返回该Partition扫描器支持的Partition类型

(3)Token管理器

l 颜色(SWT Color类的特定实例)是有限的系统资源,需要跟踪它们,对它们进行管理:不多分配,在用完之后释放它们

l Token管理器用于对Token和颜色都进行跟踪和管理,主要目的是支持允许用户在Preferences中设置颜色的功能

package org.xqtu.log4j.editor;

import java.util.HashMap;

import java.util.Iterator;

import java.util.Map;

import org.eclipse.jface.preference.IPreferenceStore;

import org.eclipse.jface.resource.StringConverter;

import org.eclipse.jface.text.TextAttribute;

import org.eclipse.jface.text.rules.IToken;

import org.eclipse.jface.text.rules.Token;

import org.eclipse.jface.util.PropertyChangeEvent;

import org.eclipse.swt.graphics.Color;

import org.eclipse.swt.graphics.RGB;

import org.eclipse.swt.widgets.Display;

public class TokenManager {

private Map colorTable = new HashMap(10);

private Map tokenTable = new HashMap(10);

private final IPreferenceStore preferenceStore;

public TokenManager(IPreferenceStore preferenceStore) {

this.preferenceStore = preferenceStore;

}

public IToken getToken(String prefKey) {

Token token = (Token) tokenTable.get(prefKey);

if (token == null) {

String colorName = preferenceStore.getString(prefKey);

RGB rgb = StringConverter.asRGB(colorName);

token = new Token(new TextAttribute(getColor(rgb)));

tokenTable.put(prefKey, token);

}

return token;

}

public void dispose() {

Iterator e = colorTable.values().iterator();

while (e.hasNext()) {

((Color) e.next()).dispose();

}

}

private Color getColor(RGB rgb) {

Color color = (Color) colorTable.get(rgb);

if (color == null) {

color = new Color(Display.getCurrent(), rgb);

colorTable.put(rgb, color);

}

return color;

}

public boolean affectsTextPresentation(PropertyChangeEvent event) {

Token token = (Token) tokenTable.get(event.getProperty());

return (token != null);

}

public void handlePreferenceStoreChanged(PropertyChangeEvent event) {

String prefKey = event.getProperty();

Token token = (Token) tokenTable.get(prefKey);

if (token != null) {

String colorName = preferenceStore.getString(prefKey);

RGB rgb = StringConverter.asRGB(colorName);

token.setData(new TextAttribute(getColor(rgb)));

}

}

}

l 开始部分定义了用于管理的Token和颜色的HashMap列表

l getToken()方法获得指定的Token:先在Token列表中查找,如果没有,就根据Preferences中获得的颜色,创建一个新的Token,并保存到Token列表中

l 在创建Token时调用getColor()方法,获得指定的颜色,其方法类似:先在颜色列表中查找,如果没有就分配一种新的颜色,并保存到颜色列表中

l TextAttribute对象用于描述文本的属性,本例只指定前景颜色,也可以指定背景颜色或式样,如粗体、斜体等

l dispose()方法用来释放所有的颜色资源

l 通常,编辑器通过注册在变化发生时调用的方法来监听Preferences的变化

Ø affectsTextPresentation()方法判断Preferences中属性的变化是否需要应用到编辑器中的文本,通常的方法只有属性是Token列表中某个Token的名字才需要应用

Ø handlePreferenceStoreChanged()方法在Preferences存储变化时应用属性变化到Toke;,同样,只有变化的属性名字是Token列表中某个Token,才会根据Preferences中指定的值替换Token的颜色

(4)注释Token扫描器

l 每个Partition需要有一个对应的Token扫描器

package org.xqtu.log4j.editor.scanners;

import org.eclipse.jface.text.rules.IToken;

import org.eclipse.jface.text.rules.RuleBasedScanner;

import org.xqtu.log4j.Log4jPlugin;

import org.xqtu.log4j.editor.TokenManager;

public class CommentScanner extends RuleBasedScanner {

public CommentScanner(TokenManager tokenManager) {

IToken commentToken = tokenManager

.getToken(Log4jPlugin.PREF_COMMENT_COLOR);

setDefaultReturnToken(commentToken);

}

}

l 所有的Token扫描器都要扩展RuleBasedScanner

l 使用TokenManager的getToken()方法获得指定的Token

l Token被指派到Partition中文本的每个部分

l 由于注释Partition中的任何东西都是注释,所以不需要提供任何规则,只要指定返回的缺省Token

(5)缺省Token扫描器

package org.xqtu.log4j.editor.scanners;

import org.eclipse.jface.text.rules.IRule;

import org.eclipse.jface.text.rules.IToken;

import org.eclipse.jface.text.rules.RuleBasedScanner;

import org.eclipse.jface.text.rules.WhitespaceRule;

import org.xqtu.log4j.Log4jPlugin;

import org.xqtu.log4j.editor.TokenManager;

public class DefaultScanner extends RuleBasedScanner {

public DefaultScanner(TokenManager tokenManager) {

IToken propertyToken = tokenManager

.getToken(Log4jPlugin.PREF_PROPERTY_COLOR);

setDefaultReturnToken(propertyToken);

setRules(new IRule[] { new WhitespaceRule(new WhitespaceDetector()) });

}

}

l 缺省Partition中除了空白字符以外的所有内容都被认为是属性名字,所以需要调用setRules()方法设置空白字符的规则

l 探测器WhitespaceDetector实现IWhitespaceDetector接口,决定当前内容中的字符是否为空白字符

package org.xqtu.log4j.editor.scanners;

import org.eclipse.jface.text.rules.IWhitespaceDetector;

public class WhitespaceDetector implements IWhitespaceDetector {

public boolean isWhitespace(char c) {

return Character.isWhitespace(c);

}

}

(6)Value值Token扫描器

l Value值Token扫描器相对要复杂一些,因为需要处理关键字和象%m、%d{hh:mm:ss a}之类的格式

package org.xqtu.log4j.editor.scanners;

import org.eclipse.jface.text.rules.IRule;

import org.eclipse.jface.text.rules.IToken;

import org.eclipse.jface.text.rules.RuleBasedScanner;

import org.eclipse.jface.text.rules.SingleLineRule;

import org.eclipse.jface.text.rules.WhitespaceRule;

import org.eclipse.jface.text.rules.WordRule;

import org.xqtu.log4j.Log4jPlugin;

import org.xqtu.log4j.editor.TokenManager;

public class ValueScanner extends RuleBasedScanner {

String[] keywords = { "ALL", "DEBUG", "ERROR", "FATAL", "INFO", "OFF",

"WARN", "INHERITED", "INHERIT", "NULL", "true", "false", };

public ValueScanner(TokenManager tokenManager) {

IToken defaultToken = tokenManager

.getToken(Log4jPlugin.PREF_DEFAULT_COLOR);

IToken formatToken = tokenManager

.getToken(Log4jPlugin.PREF_FORMAT_COLOR);

IToken keywordToken = tokenManager

.getToken(Log4jPlugin.PREF_KEYWORD_COLOR);

IRule braceRule = new SingleLineRule("{", "}", formatToken, (char) 0,

true);

WordRule keywordRule = new WordRule(new WordDetector());

for (int i = 0; i < keywords.length; i++) {

keywordRule.addWord(keywords[i], keywordToken);

}

IRule formatRule = new FormatRule(formatToken);

IRule whitespaceRule = new WhitespaceRule(new WhitespaceDetector());

setDefaultReturnToken(defaultToken);

setRules(new IRule[] { braceRule, formatRule, keywordRule,

whitespaceRule, });

}

}

l Value值Token扫描器处理包括关键字、格式化和缺省三种Token

l 在开始部分定义了关键字列表,使用WordRule来探测所有关键字Token,并应用了WordDetector探测器

l WordDetector探测器实现IWordDetector接口,决定以字母开始,包含字母或数字的内容为Word

package org.xqtu.log4j.editor.scanners;

import org.eclipse.jface.text.rules.IWordDetector;

public class WordDetector implements IWordDetector {

public boolean isWordStart(char c) {

return Character.isLetter(c);

}

public boolean isWordPart(char c) {

return Character.isLetterOrDigit(c);

}

}

l {}内的内容是作为格式化Token,使用SingleLineRule定义Token规则

l 第三个规则是自定义的格式化Token规则,在后面讲述

l 同样,需要定义空白字符规则来匹配空白字符

l 其它文本作为缺省Token返回

l 最后设置应用的Token规则

(7)自定义Token规则

l 由于Eclipse平台没有提供Log4j格式的规则,需要自定义规则

package org.xqtu.log4j.editor.scanners;

import org.eclipse.jface.text.rules.ICharacterScanner;

import org.eclipse.jface.text.rules.IRule;

import org.eclipse.jface.text.rules.IToken;

import org.eclipse.jface.text.rules.Token;

public class FormatRule implements IRule {

private final IToken token;

public FormatRule(IToken token) {

this.token = token;

}

public IToken evaluate(ICharacterScanner scanner) {

int c = scanner.read();

if (c == '%') {

do {

c = scanner.read();

} while (c != ICharacterScanner.EOF

&& (Character.isLetterOrDigit((char) c) || c == '-' || c == '.'));

scanner.unread();

return token;

}

scanner.unread();

return Token.UNDEFINED;

}

}

l 自定义规则实现IRule接口,使用evaluate()方法逐个字符进行规则匹配

l 在构造方法中,先保存要匹配的Token

l 在evaluate()方法,使用IcharacterScanner逐个读取字符,进行规则匹配

l 如果以%开始就是格式化Token,读取包含字母、数字、“-”和“.”内容,作为Token返回

l 否则返回Token.UNDEFINED,表示Token没有匹配,以便Token扫描器进行下一条规则的匹配

l 其中,调用IcharacterScanner的unread()方法对没有匹配的内容进行回退读取操作

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有