- FAQ 319: What is eScript?
- FAQ 320: Language integration phase 1: How do I compile and build programs?
- FAQ 321: How do I load source files edited outside Eclipse?
- FAQ 322: How do I run an external builder on my source files?
- FAQ 323: How do I implement a compiler that runs inside Eclipse?
- FAQ 324: How do I react to changes in source files?
- FAQ 325: How do I implement an Eclipse builder?
- FAQ 326: Where are project build specifications stored?
- FAQ 327: How do I add a builder to a given project?
- FAQ 328: How do I implement an incremental project builder?
- FAQ 329: How do I handle setup problems for a given builder?
- FAQ 330: How do I make my compiler incremental?
- FAQ 331: Language integration phase 2: How do I implement a DOM?
- FAQ 332: How do I implement a DOM for my language?
- FAQ 333: How can I ensure that my model is scalable?
- FAQ 334: Language integration phase 3: How do I edit programs?
- FAQ 335: How do I write an editor for my own language?
- FAQ 336: How do I add Content Assist to my language editor?
- FAQ 337: How do I add hover support to my text editor?
- FAQ 338: How do I create problem markers for my compiler?
- FAQ 339: How do I implement Quick Fixes for my own language?
- FAQ 340: How do I support refactoring for my own language?
- FAQ 341: How do I create an Outline view for my own language editor?
- FAQ 342: Language integration phase 4: What are the finishing touches?
- FAQ 343: What wizards do I define for my own language?
- FAQ 344: When does my language need its own nature?
- FAQ 345: When does my language need its own perspective?
- FAQ 346: How do I add documentation and help for my own language?
- FAQ 347: How do I support source-level debugging for my own language?
FAQ 335: How do I write an editor for my own language?
An editor contributes to the org.eclipse.ui.editors extension point, and, in practice, the class implementing the editor is typically a subclass of org.eclipse.ui.editors.text.TextEditor. The simplest way to familiarize yourself with the Eclipse editor framework is by creating a new plug-in with a sample XML editor (use New > Plug-in Development > Plug-in Project > ... > ... > Plug-in with an editor). This will provide you with an editor supporting syntax color highlighting, Content Assist, hover help, and more. Also be sure to check out Chapter 11 of this book, which describes an HTML editor framework. Both the XML and HTML editors show how to design and arrange your code in manageable packages.
If you want to see what the minimalist editor looks like, we did the experiment of reducing our eScript editor to a single source file with the bare minimum code required to make the smallest possible Eclipse editor ever (see Figure 19.3). We don’t suggest that you organize your code this way, but it will show you the basic information you will have to provide to give your editor have a professional look and feel with syntax highlighting and hover help.
Figure 19.3 The eScript editor
Here is the structure of our minimalist eScript editor:
public class Editor extends TextEditor { ... public Editor() { super(); setSourceViewerConfiguration(new Configuration()); } protected void createActions() { ... } ... }
In the constructor, we set up a source viewer configuration, handling such issues as Content Assist, hover help, and instructing the editor what to do while the user types text. In the inherited createActions method the editor creates its Content Assist action, used when Ctrl+Space is pressed in the editor.
Our configuration looks like this:
class Configuration extends SourceViewerConfiguration { public IPresentationReconciler getPresentationReconciler( ISourceViewer sourceViewer) { PresentationReconciler pr = new PresentationReconciler(); DefaultDamagerRepairer ddr = new DefaultDamagerRepairer(new Scanner()); pr.setRepairer(ddr, IDocument.DEFAULT_CONTENT_TYPE); pr.setDamager(ddr, IDocument.DEFAULT_CONTENT_TYPE); return pr; } IContentAssistant getContentAssistant(ISourceViewer sv) { ContentAssistant ca = new ContentAssistant(); IContentAssistProcessor cap = new CompletionProcessor(); ca.setContentAssistProcessor(cap, IDocument.DEFAULT_CONTENT_TYPE); ca.setInformationControlCreator( getInformationControlCreator(sv)); return ca; } public ITextHover getTextHover(ISourceViewer sv, String contentType) { return new TextHover(); } }
We use the default presentation reconciler, and we do not distinguish between sections in our documents. In other words, reconciliation of layout will be the same all over the document, whether we are inside a feature, a plug-in, or a method. We declare a scanner, implemented by us, and rely on the text editor framework to parse the document using our parser when it suits it.
Next, we enable Content Assist by creating a default Content Assistant and defining our own Content Assist processor. When Content Assist is activated, our processor will map the current cursor position to a node in the abstract syntax tree for the underlying document and present relevant continuations based on the currently entered string. See FAQ 336 for the implementation of our completion processor.
Finally, we create a text-hover that will return a relevant string to be shown in a hover window when we move over a given node in our abstract syntax tree. See FAQ 337 for the implementation of our ITextHover implementation.
For scanning the underlying document to draw it using different colors and fonts, we deploy RuleBasedScanner, one of the simplest scanners offered by the editor framework:
class Scanner extends RuleBasedScanner { public Scanner() { WordRule rule = new WordRule(new IWordDetector() { public boolean isWordStart(char c) { return Character.isJavaIdentifierStart(c); } public boolean isWordPart(char c) { return Character.isJavaIdentifierPart(c); } }); Token keyword = new Token(new TextAttribute( Editor.KEYWORD, null, SWT.BOLD)); Token comment = new Token( new TextAttribute(Editor.COMMENT)); Token string = new Token( new TextAttribute(Editor.STRING)); //add tokens for each reserved word for (int n = 0; n < Parser.KEYWORDS.length; n++) rule.addWord(Parser.KEYWORDS[n], keyword); setRules(new IRule[] { rule, new SingleLineRule("#", null, comment), new SingleLineRule("\"", "\"", string, '\\'), new SingleLineRule("'", "'", string, '\\'), new WhitespaceRule(new IWhitespaceDetector() { public boolean isWhitespace(char c) { return Character.isWhitespace(c); } }), }); } }
For each of the keywords in our little language, we define a word entry in our WordRule. We pass our keyword detector, together with rules for recognizing comments, strings, and white spaces to the scanner. With this simple set of rules, the scanner can segment a stream of bytes into sections and then use the underlying rules to color the sections.
Note
FAQ 211 How do I create my own editor?
FAQ 264 How do I get started with creating a custom text editor?
FAQ 336 How do I add Content Assist to my language editor?