EclipsePlug-in使用TextEditor开发自己的编辑器,实现关键字高亮和代码提示.

来源:互联网 发布:js阻止a标签跳转 编辑:程序博客网 时间:2024/04/30 09:11

        最近在开发EclipsePlug, 开发一个SQL代码编辑器, 所以就写一篇文章. 希望对大家有帮助. 让大家少走弯路. (代码可能不能运行, 但关键部分都有).  因为代码比较多. 所以可能不能一次性上传完成. 毕竟我还要修改, 空话不多说. 直接上代码.

首先是Editor类, 我取名为SQLEditor, 继承TextEditor:

package com.test.editors;import org.eclipse.core.runtime.IProgressMonitor;import org.eclipse.jface.text.BadLocationException;import org.eclipse.jface.text.IDocument;import org.eclipse.jface.text.IRegion;import org.eclipse.jface.text.formatter.IContentFormatter;import org.eclipse.swt.SWT;import org.eclipse.swt.graphics.Font;import org.eclipse.swt.graphics.FontData;import org.eclipse.swt.graphics.Point;import org.eclipse.swt.widgets.Composite;import org.eclipse.ui.IViewPart;import org.eclipse.ui.PartInitException;import org.eclipse.ui.PlatformUI;import org.eclipse.ui.editors.text.TextEditor;import com.zdk.platform.studio.dbassistant.codeassistent.ColorManager;import com.zdk.platform.studio.dbassistant.codeassistent.SQLConfiguration;import com.zdk.platform.studio.dbassistant.codeassistent.SQLDocumentProvider;/** * 类说明: SQL语句编辑器. * @author xiao天__ * */public class SQLEditor extends TextEditor {/**editorID**/public static String ID = "com.test.SQLEditor";private ColorManager colorManager;private SQLConfiguration configuration;public SQLEditor() {super();configuration = new SQLConfiguration();setSourceViewerConfiguration(configuration);setDocumentProvider(new SQLDocumentProvider());}/** * 方法说明: 设置字体. */public void initFont() {FontData fontData = new FontData("Consolas", 11, SWT.NORMAL);Font font = new Font(getEditorSite().getShell().getDisplay(), fontData);this.getSourceViewer().getTextWidget().setFont(font);}public void dispose() {if(colorManager != null) {colorManager.dispose();}super.dispose();}@Overridepublic void createPartControl(Composite parent) {super.createPartControl(parent);initFont();}}


如果大家使用的是有文件的方式. 就可以直接配置Plug-in.xml文件方式来打开SQLEditor, 而小天__使用的是不需要文件的方式来打开SQLEditor, 主要是项目需要, 所以这里给大家写两种方式:

方式一:

Plug-in.xml:

<plugin>   <extension         point="org.eclipse.ui.editors">      <editor            name="SQL编辑器"            extensions="xml"            icon="icons/sample.gif"            contributorClass="org.eclipse.ui.texteditor.BasicTextEditorActionContributor"            class="com.test.SQLEditor"            id="com.test.SQLEditor">      </editor>   </extension></plugin>

方式二:

Plug-in.xml的配置都是一样的, 因为没有文件. 所以我们必须要构建一个Input对象:

SQLEditorInput:

package com.test.editors;import java.io.ByteArrayInputStream;import java.io.InputStream;import org.eclipse.core.resources.IStorage;import org.eclipse.core.runtime.CoreException;import org.eclipse.core.runtime.IPath;import org.eclipse.jface.resource.ImageDescriptor;import org.eclipse.ui.IPersistableElement;import org.eclipse.ui.IStorageEditorInput;import org.eclipse.ui.IViewPart;import org.eclipse.ui.PartInitException;import org.eclipse.ui.PlatformUI;public class SQLEditorInput implements IStorageEditorInput {/**显示名称**/private String name;/**正文**/private String content = "";/**存储器**/public IStorage storage;public SQLEditorInput(String name) {this.name = name;storage = new IStorage() {@Overridepublic Object getAdapter(Class adapter) {return null;}@Overridepublic boolean isReadOnly() {return isReadOnly;}@Overridepublic String getName() {return SQLEditorInput.this.name;}@Overridepublic IPath getFullPath() {return null;}@Overridepublic InputStream getContents() throws CoreException {return new ByteArrayInputStream(content.getBytes());}};}public SQLEditorInput(String name, IStorage is) {this.name = name;this.storage = is;}@Overridepublic boolean exists() {return true;}@Overridepublic ImageDescriptor getImageDescriptor() {return null;}@Overridepublic String getName() {return name;}@Overridepublic IPersistableElement getPersistable() {return null;}@Overridepublic String getToolTipText() {return "SQL编辑器";}@Overridepublic Object getAdapter(Class adapter) {return null;}@Overridepublic IStorage getStorage() throws CoreException {return storage;}@Overridepublic boolean equals(Object obj) {if(obj instanceof SQLEditorInput){SQLEditorInput newDbEditorInput = (SQLEditorInput)obj;if(this.name.equals(newDbEditorInput.getName())) {return true;}}return false;}}

打开编辑器方法:

这个方法可以写在工具栏的事件里. 右键菜单里. 这个就看需求了.

public void openView() {SQLEditorInput input = new SQLEditorInput("新建查询");try {page.openEditor(input, "com.test.SQLEditor");} catch (PartInitException e) {e.printStackTrace();}}

SQLConfiguration类:

package com.zdk.platform.studio.dbassistant.codeassistent;import org.eclipse.jface.text.IDocument;import org.eclipse.jface.text.contentassist.ContentAssistant;import org.eclipse.jface.text.contentassist.IContentAssistant;import org.eclipse.jface.text.formatter.ContentFormatter;import org.eclipse.jface.text.formatter.IContentFormatter;import org.eclipse.jface.text.presentation.IPresentationReconciler;import org.eclipse.jface.text.presentation.PresentationReconciler;import org.eclipse.jface.text.rules.DefaultDamagerRepairer;import org.eclipse.jface.text.source.ISourceViewer;import org.eclipse.jface.text.source.SourceViewerConfiguration;import com.zdk.platform.studio.dbassistant.codeassistent.assistent.SQLContentAssistent;public class SQLConfiguration extends SourceViewerConfiguration {private SQLContentAssistent assistent;public IPresentationReconciler getPresentationReconciler(ISourceViewer sourceViewer) {PresentationReconciler reconciler = new PresentationReconciler();DefaultDamagerRepairer dr = new DefaultDamagerRepairer(new SQLPartitionScanner());reconciler.setDamager(dr, IDocument.DEFAULT_CONTENT_TYPE);reconciler.setRepairer(dr, IDocument.DEFAULT_CONTENT_TYPE);return reconciler;}@Overridepublic IContentFormatter getContentFormatter(ISourceViewer sourceViewer) {ContentFormatter formatter = new ContentFormatter();formatter.setFormattingStrategy(new SQLFormattingStrategy(), IDocument.DEFAULT_CONTENT_TYPE);formatter.enablePartitionAwareFormatting(true);return formatter;}/** * 设置自动提示. */@Overridepublic IContentAssistant getContentAssistant(ISourceViewer sourceViewer) {ContentAssistant contentAssistent = new ContentAssistant();assistent = new SQLContentAssistent();contentAssistent.setContentAssistProcessor(assistent, IDocument.DEFAULT_CONTENT_TYPE);contentAssistent.enableAutoActivation(true);contentAssistent.setAutoActivationDelay(200);return contentAssistent;}public DBConfig getDbConfig() {return dbConfig;}}

SQLDocumentProvider类(说实话这个类.小天__都不清楚有什么用):

package com.zdk.platform.studio.dbassistant.codeassistent;import org.eclipse.core.runtime.CoreException;import org.eclipse.jface.text.IDocument;import org.eclipse.jface.text.IDocumentPartitioner;import org.eclipse.jface.text.rules.FastPartitioner;import org.eclipse.ui.editors.text.FileDocumentProvider;public class SQLDocumentProvider extends FileDocumentProvider {protected IDocument createDocument(Object element) throws CoreException {IDocument document = super.createDocument(element);if (document != null) {IDocumentPartitioner partitioner =new FastPartitioner(new SQLPartitionScanner(),new String[] { });partitioner.connect(document);document.setDocumentPartitioner(partitioner);}return document;}}


代码高亮部分:

ColorManager类:

package com.zdk.platform.studio.dbassistant.codeassistent;import java.util.HashMap;import java.util.Iterator;import java.util.Map;import org.eclipse.swt.graphics.Color;import org.eclipse.swt.graphics.RGB;import org.eclipse.swt.widgets.Display;/** * 类说明: 颜色管理类. * @author 小天__ * */public class ColorManager {/**注释颜色**/public static final RGB COLOR_COMMENT = new RGB(0, 128, 0);/**关键字颜色**/public static final RGB COLOR_KEYWORD = new RGB(128, 0, 0);/**普通文本颜色**/public static final RGB COLOR_TEXT = new RGB(0, 0, 0);protected static Map fColorTable = new HashMap(10);public void dispose() {Iterator e = fColorTable.values().iterator();while (e.hasNext()) ((Color) e.next()).dispose();}public static Color getColor(RGB rgb) {Color color = (Color) fColorTable.get(rgb);if (color == null) {color = new Color(Display.getCurrent(), rgb);fColorTable.put(rgb, color);}return color;}}

SQLPartitionScanner:

package com.test.codeassistent;import org.eclipse.jface.text.TextAttribute;import org.eclipse.jface.text.rules.EndOfLineRule;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;import com.test.rule.KeyWordDetector;import com.test.rule.KeyWordRule;public class SQLPartitionScanner extends RuleBasedPartitionScanner {private TextAttribute keywordAttr = new TextAttribute(ColorManager.getColor(ColorManager.COLOR_KEYWORD));public SQLPartitionScanner() {IPredicateRule[] rules = new IPredicateRule[1];rules[0] = new KeyWordRule(new KeyWordDetector(), new Token(keywordAttr));setPredicateRules(rules);}}

KeyWordRule:

package com.zdk.platform.studio.dbassistant.codeassistent.rule;import org.eclipse.jface.text.rules.ICharacterScanner;import org.eclipse.jface.text.rules.IPredicateRule;import org.eclipse.jface.text.rules.IToken;import org.eclipse.jface.text.rules.IWordDetector;import org.eclipse.jface.text.rules.Token;import org.eclipse.jface.text.rules.WordRule;import com.test.SQLPartitionScanner;public class KeyWordRule extends WordRule implements IPredicateRule {private StringBuffer fBuffer= new StringBuffer();private boolean fIgnoreCase= false;/**关键字**/public String keywords = "insert,update,delete,select";public KeyWordRule(IWordDetector detector, IToken defaultToken) {super(detector, new Token(SQLPartitionScanner.textAttr));//增加关键字String[] keywordArray = keywords.split(",");for (int i = 0; i < keywordArray.length; i++) {String keywrod = keywordArray[i];addWord(keywrod, defaultToken);}}public IToken evaluate(ICharacterScanner scanner) {int c= scanner.read();if (c != ICharacterScanner.EOF && fDetector.isWordStart((char) c)) {if (fColumn == UNDEFINED || (fColumn == scanner.getColumn() - 1)) {fBuffer.setLength(0);do {fBuffer.append((char) c);c= scanner.read();} while (c != ICharacterScanner.EOF && fDetector.isWordPart((char) c));scanner.unread();String buffer= fBuffer.toString();if (fIgnoreCase) {buffer = buffer.toLowerCase();}IToken token= (IToken)fWords.get(buffer);if (token != null) {return token;}if (fDefaultToken.isUndefined()) {unreadBuffer(scanner);}return fDefaultToken;}}scanner.unread();return Token.UNDEFINED;}@Overridepublic IToken getSuccessToken() {return Token.UNDEFINED;}@Overridepublic IToken evaluate(ICharacterScanner scanner, boolean resume) {return this.fDefaultToken;}}

KeyWordDetector:

package com.zdk.platform.studio.dbassistant.codeassistent.rule;/******************************************************************************* * Copyright (c) 2000 2005 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: *     IBM Corporation - initial API and implementation *     QNX Software System *******************************************************************************/import org.eclipse.jface.text.rules.IWordDetector;/** * A C aware word detector. */public class KeyWordDetector implements IWordDetector {/** * @see IWordDetector#isWordIdentifierStart */public boolean isWordStart(char c) {if(64 < c && c < 123 || c == '=') {//大写字母A-Z, 小写字母a-z;return true;}return false;}/** * @see IWordDetector#isWordIdentifierPart */public boolean isWordPart(char c) {if(64 < c && c < 123 || c == '=') {//大写字母A-Z, 小写字母a-z;return true;}return false;}}

代码提示部分:

SQLContentAssistent:

package com.test.assistent;import java.util.ArrayList;import java.util.List;import org.eclipse.jface.text.BadLocationException;import org.eclipse.jface.text.IDocument;import org.eclipse.jface.text.ITextViewer;import org.eclipse.jface.text.contentassist.CompletionProposal;import org.eclipse.jface.text.contentassist.ICompletionProposal;import org.eclipse.jface.text.contentassist.IContentAssistProcessor;import org.eclipse.jface.text.contentassist.IContextInformation;import org.eclipse.jface.text.contentassist.IContextInformationValidator;import com.zdk.platform.studio.pojo.DBConfig;public class SQLContentAssistent implements IContentAssistProcessor { /**提示集合**/public List<IAssistentContent> assistentContentList = new ArrayList<IAssistentContent>();/**开始位置**/public int startIndex = 0;/**当前文档**/public IDocument doc;/**数据连接对象**/private DBConfig dbConfig;/** * 构造方法: 添加提示种类. */public SQLContentAssistent() {super();assistentContentList.add(new KeywordAssistentData());}@Overridepublic ICompletionProposal[] computeCompletionProposals(ITextViewer viewer, int offset) {this.doc = viewer.getDocument();List list = new KeywordAssistentData().getAssistentData(this.doc, offset);return (CompletionProposal[]) list.toArray(new CompletionProposal[list.size()]);}@Overridepublic IContextInformation[] computeContextInformation(ITextViewer viewer, int offset) {// TODO 自动生成的方法存根return null;}/** * 设置何时激活 */@Overridepublic char[] getCompletionProposalAutoActivationCharacters() {return new char[] {'.'};}@Overridepublic char[] getContextInformationAutoActivationCharacters() {return null;}@Overridepublic String getErrorMessage() {// TODO 自动生成的方法存根return null;}@Overridepublic IContextInformationValidator getContextInformationValidator() {// TODO 自动生成的方法存根return null;}/** * 方法说明: 获取提示前面的字符串. * @param doc * @param offest * @return */public String getFrontText(IDocument doc, int offest) {StringBuffer buf = new StringBuffer();while(true) {//循环添加关键字.try {char c = doc.getChar(--offest);startIndex = offest;if(Character.isWhitespace(c)) {startIndex++;break;}if(c == ';' || c == '(' || c == ')' || c == '{' || c == '}' || c == ',') {//结束符号.startIndex++;break;}buf.append(c);} catch (BadLocationException e) {break;}}return buf.reverse().toString();}}

KeywordAssistentData:

package com.test.assistent;import java.util.ArrayList;import java.util.List;import java.util.regex.Matcher;import java.util.regex.Pattern;import org.eclipse.jface.text.BadLocationException;import org.eclipse.jface.text.IDocument;import org.eclipse.jface.text.contentassist.CompletionProposal;import com.zdk.platform.studio.dbassistant.codeassistent.Contents;/** * 类说明: 关键字提示数据类. * @author Administrator * */public class KeywordAssistentData implements IAssistentContent {private int start = 0; @Overridepublic List<CompletionProposal> getAssistentData(IDocument doc, int offset) {String str = getFrontText(doc, offset);List<CompletionProposal> list = new ArrayList<CompletionProposal>();//用正则匹配.Pattern p = null;Matcher m = null;for (int i = 0; i < Contents.KEY_WORD_ARRAY.length; i++) {String keyWord = Contents.KEY_WORD_ARRAY[i];p = Pattern.compile("(^" + str + ")", Pattern.CASE_INSENSITIVE);m = p.matcher(keyWord);if(m.find()) {String insert = Contents.KEY_WORD_ARRAY[i];//创建替换类容.  insert:替换文本, offset:替换其实位置.//0:替换结束位置.偏移量, insert.length:替换完成后.光标位置偏移量.CompletionProposal proposal = new CompletionProposal(insert, start, offset - start, insert.length());list.add(proposal);}}return list;}/** * 方法说明: 获取提示前面的字符串. * @param doc * @param offest * @return */public String getFrontText(IDocument doc, int offest) {StringBuffer buf = new StringBuffer();while(true) {//循环添加关键字.try {char c = doc.getChar(--offest);start = offest;if(Character.isWhitespace(c)) {start++;break;}if(c == ';' || c == '(' || c == ')' || c == '{' || c == '}' || c == ',') {//结束符号.start++;break;}buf.append(c);} catch (BadLocationException e) {break;}}return buf.reverse().toString();}}

以上就是大部分代码了.










1 0
原创粉丝点击