1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-01-18 07:52:14 +01:00

Libraries now support syntax coloring and are built on IDE startup.

This commit is contained in:
David A. Mellis 2006-04-09 12:40:34 +00:00
parent 56c86b6f67
commit fb34821d84
7 changed files with 387 additions and 211 deletions

View File

@ -210,6 +210,9 @@ public class Base {
// show the window
editor.show();
// attempt to build libraries
editor.prepareLibraries();
// check for updates
if (Preferences.getBoolean("update.check")) {
new UpdateCheck(editor);
@ -1075,7 +1078,8 @@ public class Base {
}
return null;
}
//////////////////////////////////////////////////////////////
// STRINGS
@ -1229,7 +1233,4 @@ public class Base {
return splits;
}
}

View File

@ -330,6 +330,29 @@ public class Editor extends JFrame
// ...................................................................
/**
* Builds any unbuilt buildable libraries
* Adds syntax coloring from those libraries (if exists)
* Rebuilds sketchbook menu with library examples (if they exist)
*/
public void prepareLibraries() {
// build any unbuilt libraries
try {
LibraryManager libraryManager = new LibraryManager();
libraryManager.buildAllUnbuilt();
// update syntax coloring table
libraryManager.addSyntaxColoring(new PdeKeywords());
} catch (RunnerException re) {
message("Error compiling library ...");
error(re);
} catch (Exception ex) {
ex.printStackTrace();
}
// update sketchbook menu, this adds examples of any built libs
sketchbook.rebuildMenus();
}
// ...................................................................
/**
* Post-constructor setup for the editor area. Loads the last
@ -666,7 +689,6 @@ public class Editor extends JFrame
});
menu.add(item);
*/
item = new JMenuItem("Archive Sketch");
item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
@ -738,7 +760,6 @@ public class Editor extends JFrame
return menu;
}
// taken from an ancient version of processing
class SerialMenuListener implements ActionListener {
//public SerialMenuListener() { }
@ -751,16 +772,14 @@ public class Editor extends JFrame
for (int i = 0; i < count; i++) {
((JCheckBoxMenuItem)serialMenu.getItem(i)).setState(false);
}
JCheckBoxMenuItem item = (JCheckBoxMenuItem)e.getSource();
item.setState(true);
String name = item.getLabel();
//System.out.println(item.getLabel());
Preferences.set("serial.port", name);
//System.out.println("set to " + get("serial.port"));
}
/*
public void actionPerformed(ActionEvent e) {
System.out.println(e.getSource());
@ -840,7 +859,6 @@ public class Editor extends JFrame
//serialMenu.add(item);
}
protected JMenu buildHelpMenu() {
JMenu menu = new JMenu("Help");
JMenuItem item;
@ -1831,6 +1849,7 @@ public class Editor extends JFrame
//String what = sketch.isLibrary() ? "Applet" : "Library";
//message("Exporting " + what + "...");
message("Uploading to I/O Board...");
SwingUtilities.invokeLater(new Runnable() {
public void run() {
try {

View File

@ -19,6 +19,8 @@
package processing.app;
import processing.app.syntax.*;
import java.io.*;
import java.util.*;
import java.util.zip.*;
@ -35,6 +37,7 @@ import javax.swing.event.*;
public class Library implements MessageConsumer{
private File libFolder;
private File utilityFolder;
private LibraryManager libManager;
RunnerException exception;
@ -48,10 +51,13 @@ public class Library implements MessageConsumer{
{
libFolder = folder;
libManager = manager;
utilityFolder = getUtilityFolder();
/* for debug output
// for debug output
/*
System.out.println("library: " + getName());
System.out.println("folder: " + getFolder());
System.out.println("utility: " + utilityFolder);
System.out.println("built: " + isBuilt());
System.out.println("buildable: " + isBuildable());
System.out.println("o files: " + getObjectFiles().length);
@ -85,12 +91,7 @@ public class Library implements MessageConsumer{
*/
public boolean isBuilt()
{
FileFilter onlyObjectFiles = new FileFilter() {
public boolean accept(File file) {
return file.getName().endsWith(".o");
}
};
if(0 < (libFolder.listFiles(onlyObjectFiles)).length){
if(getObjectFiles().length >= (getCSourceFiles().length + getCPPSourceFiles().length)){
return true;
}
return false;
@ -98,16 +99,11 @@ public class Library implements MessageConsumer{
/*
* Tests if library is buildable
* @return True if library has .cpp files, false otherwise
* @return True if library has source files, false otherwise
*/
public boolean isBuildable()
{
FileFilter onlySourceFiles = new FileFilter() {
public boolean accept(File file) {
return (file.getName()).endsWith(".cpp");
}
};
if(0 < (libFolder.listFiles(onlySourceFiles)).length){
if(0 < (getCSourceFiles().length + getCPPSourceFiles().length)){
return true;
}
return false;
@ -127,6 +123,29 @@ public class Library implements MessageConsumer{
return false;
}
/*
* Scans for library "utility" folder
* @return File object of library's "utility" folder, or null
*/
private File getUtilityFolder()
{
FileFilter filter = new FileFilter() {
public boolean accept(File file) {
if(file.isDirectory()){
if((file.getName()).equalsIgnoreCase("utility")){
return true;
}
}
return false;
}
};
File[] files = libFolder.listFiles(filter);
if(files.length > 0){
return files[0];
}
return null;
}
/*
* Finds examples folder
* @return "examples" folder as file object or null
@ -195,21 +214,33 @@ public class Library implements MessageConsumer{
/*
* List of object files for linking
* @return Array of library's object files as File objects
* @return Array of object files as File objects
*/
public File[] getObjectFiles()
private File[] getObjectFiles(File folder)
{
FileFilter onlyObjectFiles = new FileFilter() {
public boolean accept(File file) {
return (file.getName()).endsWith(".o");
}
};
return libFolder.listFiles(onlyObjectFiles);
return folder.listFiles(onlyObjectFiles);
}
public File[] getObjectFiles()
{
if(null == utilityFolder){
return getObjectFiles(libFolder);
}
File[] libraryObjects = getObjectFiles(libFolder);
File[] utilityObjects = getObjectFiles(utilityFolder);
File[] objects = new File[libraryObjects.length + utilityObjects.length];
System.arraycopy(libraryObjects, 0, objects, 0, libraryObjects.length);
System.arraycopy(utilityObjects, 0, objects, libraryObjects.length, utilityObjects.length);
return objects;
}
/*
* List of header source files for inclusion
* @return Array of library's header source files as File objects
* @return Array of header source files as File objects
*/
public File[] getHeaderFiles()
{
@ -222,31 +253,55 @@ public class Library implements MessageConsumer{
}
/*
* List of C source files for compiling
* @return Array of library's C source files as File objects
* List of library's C source files for compiling
* @return Array of C source files as File objects
*/
private File[] getCSourceFiles()
private File[] getCSourceFiles(File folder)
{
FileFilter onlyCFiles = new FileFilter() {
public boolean accept(File file) {
return (file.getName()).endsWith(".c");
}
};
return libFolder.listFiles(onlyCFiles);
return folder.listFiles(onlyCFiles);
}
private File[] getCSourceFiles()
{
if(null == utilityFolder){
return getCSourceFiles(libFolder);
}
File[] librarySources = getCSourceFiles(libFolder);
File[] utilitySources = getCSourceFiles(utilityFolder);
File[] sources = new File[librarySources.length + utilitySources.length];
System.arraycopy(librarySources, 0, sources, 0, librarySources.length);
System.arraycopy(utilitySources, 0, sources, librarySources.length, utilitySources.length);
return sources;
}
/*
* List of C++ source files for compiling
* @return Array of library's C++ source files as File objects
* @return Array of C++ source files as File objects
*/
private File[] getCPPSourceFiles()
private File[] getCPPSourceFiles(File folder)
{
FileFilter onlyCPPFiles = new FileFilter() {
public boolean accept(File file) {
return (file.getName()).endsWith(".cpp");
}
};
return libFolder.listFiles(onlyCPPFiles);
return folder.listFiles(onlyCPPFiles);
}
private File[] getCPPSourceFiles()
{
if(null == utilityFolder){
return getCPPSourceFiles(libFolder);
}
File[] librarySources = getCPPSourceFiles(libFolder);
File[] utilitySources = getCPPSourceFiles(utilityFolder);
File[] sources = new File[librarySources.length + utilitySources.length];
System.arraycopy(librarySources, 0, sources, 0, librarySources.length);
System.arraycopy(utilitySources, 0, sources, librarySources.length, utilitySources.length);
return sources;
}
/*
@ -255,157 +310,170 @@ public class Library implements MessageConsumer{
*/
public boolean build() throws RunnerException
{
if(isBuildable()){
String userDir = System.getProperty("user.dir") + File.separator;
String[] baseCompileCommandC = new String[] {
((!Base.isMacOS()) ? "tools/avr/bin/avr-gcc" : userDir + "tools/avr/bin/avr-gcc"),
"-c",
"-g",
"-Os",
"-Wall",
"-mmcu=" + Preferences.get("build.mcu"),
"-DF_CPU=" + Preferences.get("build.f_cpu"),
"-I" + libManager.getTarget().getPath(),
"-I" + getFolder(),
};
String[] baseCompileCommandCPP = new String[] {
((!Base.isMacOS()) ? "tools/avr/bin/avr-g++" : userDir + "tools/avr/bin/avr-g++"),
"-c",
"-g",
"-Os",
"-Wall",
"-fno-exceptions",
"-mmcu=" + Preferences.get("build.mcu"),
"-DF_CPU=" + Preferences.get("build.f_cpu"),
"-I" + libManager.getTarget().getPath(),
"-I" + getFolder(),
};
// use built lib directories in include paths when searching for headers
// this allows libs to use other libs easily
String[] libDirs = libManager.getFolderPaths();
String[] compileCommandC = new String[baseCompileCommandC.length + libDirs.length + 2];
String[] compileCommandCPP = new String[baseCompileCommandCPP.length + libDirs.length + 2];
System.arraycopy(baseCompileCommandC, 0, compileCommandC, 0, baseCompileCommandC.length);
System.arraycopy(baseCompileCommandCPP, 0, compileCommandCPP, 0, baseCompileCommandCPP.length);
for (int i = 0; i < libDirs.length; ++i) {
compileCommandC[baseCompileCommandC.length + i] = "-I" + libDirs[i];
compileCommandCPP[baseCompileCommandCPP.length + i] = "-I" + libDirs[i];
}
File[] sourcesC = getCSourceFiles();
File[] sourcesCPP = getCPPSourceFiles();
// execute the compiler, and create threads to deal
// with the input and error streams
//
int result = 0;
try {
String nameSansExtension;
Process process;
boolean compiling = true;
// compile c sources
for(int i = 0; i < sourcesC.length; ++i) {
nameSansExtension = sourcesC[i].getName();
nameSansExtension = nameSansExtension.substring(0, nameSansExtension.length() - 2); // -2 because ".c"
compileCommandC[compileCommandC.length - 2] = sourcesC[i].getPath();
compileCommandC[compileCommandC.length - 1] = "-o" + getFolder() + File.separator + nameSansExtension + ".o";
process = Runtime.getRuntime().exec(compileCommandC);
new MessageSiphon(process.getInputStream(), this);
new MessageSiphon(process.getErrorStream(), this);
// wait for the process to finish. if interrupted
// before waitFor returns, continue waiting
//
compiling = true;
while (compiling) {
try {
result = process.waitFor();
//System.out.println("result is " + result);
compiling = false;
} catch (InterruptedException ignored) { }
}
if (exception != null) {
exception.hideStackTrace = true;
throw exception;
}
if(result != 0){
return false;
}
}
// compile c++ sources
for(int i = 0; i < sourcesCPP.length; ++i) {
nameSansExtension = sourcesCPP[i].getName();
nameSansExtension = nameSansExtension.substring(0, nameSansExtension.length() - 4); // -4 because ".cpp"
compileCommandCPP[compileCommandCPP.length - 2] = sourcesCPP[i].getPath();
compileCommandCPP[compileCommandCPP.length - 1] = "-o" + getFolder() + File.separator + nameSansExtension + ".o";
process = Runtime.getRuntime().exec(compileCommandCPP);
new MessageSiphon(process.getInputStream(), this);
new MessageSiphon(process.getErrorStream(), this);
// wait for the process to finish. if interrupted
// before waitFor returns, continue waiting
//
compiling = true;
while (compiling) {
try {
result = process.waitFor();
//System.out.println("result is " + result);
compiling = false;
} catch (InterruptedException ignored) { }
}
if (exception != null) {
exception.hideStackTrace = true;
throw exception;
}
if(result != 0){
return false;
}
}
} catch (Exception e) {
String msg = e.getMessage();
if ((msg != null) && (msg.indexOf("avr-gcc: not found") != -1)) {
Base.showWarning("Compiler error",
"Could not find the compiler.\n" +
"avr-gcc is missing from your PATH,\n" +
"see readme.txt for help.", null);
return false;
} else if ((msg != null) && (msg.indexOf("avr-g++: not found") != -1)) {
Base.showWarning("Compiler error",
"Could not find the compiler.\n" +
"avr-g++ is missing from your PATH,\n" +
"see readme.txt for help.", null);
return false;
} else {
e.printStackTrace();
result = -1;
}
}
// an error was queued up by message()
if (exception != null) {
throw exception;
}
if (result != 0 && result != 1 ) {
Base.openURL(BUGS_URL);
throw new RunnerException(SUPER_BADNESS);
}
// success would mean that 'result' is set to zero
return (result == 0); // ? true : false;
// fail if library is not buildable (contains no sources)
if(!isBuildable()){
return false;
}
return false; // library is not buildable (contains no sources)
String userDir = System.getProperty("user.dir") + File.separator;
String[] baseCompileCommandC = new String[] {
((!Base.isMacOS()) ? "tools/avr/bin/avr-gcc" : userDir + "tools/avr/bin/avr-gcc"),
"-c",
"-g",
"-Os",
"-Wall",
"-mmcu=" + Preferences.get("build.mcu"),
"-DF_CPU=" + Preferences.get("build.f_cpu"),
"-I" + libManager.getTarget().getPath(),
"-I" + getFolder(),
};
String[] baseCompileCommandCPP = new String[] {
((!Base.isMacOS()) ? "tools/avr/bin/avr-g++" : userDir + "tools/avr/bin/avr-g++"),
"-c",
"-g",
"-Os",
"-Wall",
"-fno-exceptions",
"-mmcu=" + Preferences.get("build.mcu"),
"-DF_CPU=" + Preferences.get("build.f_cpu"),
"-I" + libManager.getTarget().getPath(),
"-I" + getFolder(),
};
// use built lib directories in include paths when searching for headers
// this allows libs to use other libs easily
int extraSpots = 2; // two spots for file path and -o portions
utilityFolder = getUtilityFolder(); // refresh status of utility folder
if(null != utilityFolder){
extraSpots = 3; // an extra spot for utility folder as include
}
String[] libDirs = libManager.getFolderPaths();
String[] compileCommandC = new String[baseCompileCommandC.length + libDirs.length + extraSpots];
String[] compileCommandCPP = new String[baseCompileCommandCPP.length + libDirs.length + extraSpots];
System.arraycopy(baseCompileCommandC, 0, compileCommandC, 0, baseCompileCommandC.length);
System.arraycopy(baseCompileCommandCPP, 0, compileCommandCPP, 0, baseCompileCommandCPP.length);
for (int i = 0; i < libDirs.length; ++i) {
compileCommandC[baseCompileCommandC.length + i] = "-I" + libDirs[i];
compileCommandCPP[baseCompileCommandCPP.length + i] = "-I" + libDirs[i];
}
// add this library's "utility" folder to inclusion paths
if(null != utilityFolder){
compileCommandC[compileCommandC.length - 3] = "-I" + utilityFolder.getPath();
compileCommandCPP[compileCommandCPP.length - 3] = "-I" + utilityFolder.getPath();
}
File[] sourcesC = getCSourceFiles();
File[] sourcesCPP = getCPPSourceFiles();
// execute the compiler, and create threads to deal
// with the input and error streams
//
int result = 0;
try {
String pathSansExtension;
Process process;
boolean compiling = true;
// compile c sources
for(int i = 0; i < sourcesC.length; ++i) {
pathSansExtension = sourcesC[i].getPath();
pathSansExtension = pathSansExtension.substring(0, pathSansExtension.length() - 2); // -2 because ".c"
compileCommandC[compileCommandC.length - 2] = sourcesC[i].getPath();
compileCommandC[compileCommandC.length - 1] = "-o" + pathSansExtension + ".o";
process = Runtime.getRuntime().exec(compileCommandC);
new MessageSiphon(process.getInputStream(), this);
new MessageSiphon(process.getErrorStream(), this);
// wait for the process to finish. if interrupted
// before waitFor returns, continue waiting
//
compiling = true;
while (compiling) {
try {
result = process.waitFor();
//System.out.println("result is " + result);
compiling = false;
} catch (InterruptedException ignored) { }
}
if (exception != null) {
exception.hideStackTrace = true;
throw exception;
}
if(result != 0){
return false;
}
}
// compile c++ sources
for(int i = 0; i < sourcesCPP.length; ++i) {
pathSansExtension = sourcesCPP[i].getPath();
pathSansExtension = pathSansExtension.substring(0, pathSansExtension.length() - 4); // -4 because ".cpp"
compileCommandCPP[compileCommandCPP.length - 2] = sourcesCPP[i].getPath();
compileCommandCPP[compileCommandCPP.length - 1] = "-o" + pathSansExtension + ".o";
process = Runtime.getRuntime().exec(compileCommandCPP);
new MessageSiphon(process.getInputStream(), this);
new MessageSiphon(process.getErrorStream(), this);
// wait for the process to finish. if interrupted
// before waitFor returns, continue waiting
//
compiling = true;
while (compiling) {
try {
result = process.waitFor();
//System.out.println("result is " + result);
compiling = false;
} catch (InterruptedException ignored) { }
}
if (exception != null) {
exception.hideStackTrace = true;
throw exception;
}
if(result != 0){
return false;
}
}
} catch (Exception e) {
String msg = e.getMessage();
if ((msg != null) && (msg.indexOf("avr-gcc: not found") != -1)) {
Base.showWarning("Compiler error",
"Could not find the compiler.\n" +
"avr-gcc is missing from your PATH,\n" +
"see readme.txt for help.", null);
return false;
} else if ((msg != null) && (msg.indexOf("avr-g++: not found") != -1)) {
Base.showWarning("Compiler error",
"Could not find the compiler.\n" +
"avr-g++ is missing from your PATH,\n" +
"see readme.txt for help.", null);
return false;
} else {
e.printStackTrace();
result = -1;
}
}
// an error was queued up by message()
if (exception != null) {
throw exception;
}
if (result != 0 && result != 1 ) {
Base.openURL(BUGS_URL);
throw new RunnerException(SUPER_BADNESS);
}
// success would mean that 'result' is set to zero
return (result == 0); // ? true : false;
}
/**
@ -440,5 +508,69 @@ public class Library implements MessageConsumer{
exception = new RunnerException("Error building library \"" + getName() + "\"");
}
}
/**
* Handles loading of keywords file.
* It is recommended that a # sign be used for comments
* inside keywords.txt.
*/
public void addSyntaxColors(PdeKeywords keywords) {
File keywordsFile = new File(libFolder.getPath() + File.separator + "keywords.txt");
// do not bother if no keywords file to read
// should reprimand negligent library writers?!
if(!keywordsFile.exists() || !keywordsFile.canRead()){
return;
}
try{
// open file stream in the verbose java way
InputStream input = new FileInputStream(keywordsFile);
InputStreamReader isr = new InputStreamReader(input);
BufferedReader reader = new BufferedReader(isr);
String line = null;
while ((line = reader.readLine()) != null) {
// skip empty and whitespace lines
if (line.trim().length() == 0){
continue;
}
// skip lines without tabs
if (line.indexOf('\t') == -1){
continue;
}
String pieces[] = Base.split(line, '\t');
if (pieces.length >= 2) {
String keyword = pieces[0].trim();
String coloring = pieces[1].trim();
if (coloring.length() > 0) {
// text will be KEYWORD or LITERAL
boolean isKey = (coloring.charAt(0) == 'K');
// KEYWORD1 -> 0, KEYWORD2 -> 1, etc
int num = coloring.charAt(coloring.length() - 1) - '1';
byte id = (byte)((isKey ? Token.KEYWORD1 : Token.LITERAL1) + num);
//System.out.println("got " + (isKey ? "keyword" : "literal") + (num+1) + " for " + keyword);
PdeKeywords.getKeywordColoring().add(keyword, id);
}
}
}
// close file stream
reader.close();
} catch (Exception e) {
Base.showError("Problem Loading Keywords",
"Could not load or interpret 'keywords.txt' in " + getName() + " library.\n" +
"This must be corrected before distributing.", e);
}
}
}

View File

@ -19,6 +19,8 @@
package processing.app;
import processing.app.syntax.*;
import java.io.*;
import java.util.*;
import java.util.zip.*;
@ -225,4 +227,17 @@ public class LibraryManager {
}
}
}
/*
* Add syntax coloring
*/
public void addSyntaxColoring(PdeKeywords keywords) {
Library library;
Collection libraries = getBuiltLibraries();
Iterator iterator = libraries.iterator();
while(iterator.hasNext()){
library = (Library)iterator.next();
library.addSyntaxColors(keywords);
}
}
}

View File

@ -1125,7 +1125,7 @@ public class Sketch {
public void importLibrary(String jarPath) {
System.out.println(jarPath);
//System.out.println(jarPath);
// make sure the user didn't hide the sketch folder
ensureExistence();
@ -1340,17 +1340,7 @@ public class Sketch {
// build unbuilt buildable libraries
// completely independent from sketch, so run all the time
LibraryManager libraryManager;
try {
libraryManager = new LibraryManager();
libraryManager.buildAllUnbuilt();
} catch (RunnerException re) {
throw new RunnerException(re.getMessage());
} catch (Exception ex) {
throw new RunnerException(ex.toString());
}
// update sketchbook menu, this adds examples of any built libs
editor.sketchbook.rebuildMenus();
editor.prepareLibraries();
// make sure the user didn't hide the sketch folder
ensureExistence();
@ -1563,19 +1553,27 @@ public class Sketch {
importedLibraries = new Vector();
String imports[] = preprocessor.extraImports;
Collection libraries = libraryManager.getAll();
for (Iterator i = libraries.iterator(); i.hasNext(); ) {
Library library = (Library) i.next();
File[] headerFiles = library.getHeaderFiles();
for (int j = 0; j < headerFiles.length; j++)
for (int k = 0; k < imports.length; k++)
if (headerFiles[j].getName().equals(imports[k]) &&
!importedLibraries.contains(library)) {
importedLibraries.add(library);
//System.out.println("Adding library " + library.getName());
}
try {
LibraryManager libraryManager = new LibraryManager();
Collection libraries = libraryManager.getAll();
for (Iterator i = libraries.iterator(); i.hasNext(); ) {
Library library = (Library) i.next();
File[] headerFiles = library.getHeaderFiles();
for (int j = 0; j < headerFiles.length; j++)
for (int k = 0; k < imports.length; k++)
if (headerFiles[j].getName().equals(imports[k]) &&
!importedLibraries.contains(library)) {
importedLibraries.add(library);
//System.out.println("Adding library " + library.getName());
}
}
} catch (IOException e) {
System.err.println("Error finding libraries:");
e.printStackTrace();
throw new RunnerException(e.getMessage());
}
//for (int i = 0; i < imports.length; i++) {
/*
// remove things up to the last dot

View File

@ -346,10 +346,10 @@ public class Sketchbook {
if (addLibraries(importMenu, new File(getSketchbookPath()))) {
importMenu.addSeparator();
}
*/
if (addLibraries(importMenu, examplesFolder)) {
importMenu.addSeparator();
}
*/
addLibraries(importMenu, librariesFolder);
//System.out.println("libraries cp is now " + librariesClassPath);

View File

@ -4,7 +4,7 @@
PdeKeywords - handles text coloring and links to html reference
Part of the Processing project - http://processing.org
Copyright (c) 2004-05 Ben Fry and Casey Reas
Copyright (c) 2004-06 Ben Fry and Casey Reas
Copyright (c) 2001-04 Massachusetts Institute of Technology
This program is free software; you can redistribute it and/or modify
@ -68,6 +68,13 @@ public class PdeKeywords extends CTokenMarker {
//System.out.println("line is " + line);
// in case there's any garbage on the line
//if (line.trim().length() == 0) continue;
// don't bother if line begins with hash
if(0 < line.length()){
if('#' == line.charAt(0)){
continue;
}
}
String pieces[] = Base.split(line, '\t');
if (pieces.length >= 2) {
@ -119,4 +126,8 @@ public class PdeKeywords extends CTokenMarker {
static public String getReference(String keyword) {
return (String) keywordToReference.get(keyword);
}
static public KeywordMap getKeywordColoring() {
return keywordColoring;
}
}