Skip to content

Commit 861e920

Browse files
committed
Add a script interpreter UI
Migrated from imagej-ui-swing. Needs to be revamped to use SJC's new ScriptREPL. Ultimately the UI should have: * a JList or JComboBox of languages * a JTable of variable names and values
1 parent 7df0f50 commit 861e920

10 files changed

Lines changed: 1325 additions & 0 deletions

File tree

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* #%L
3+
* SciJava UI components for Java Swing.
4+
* %%
5+
* Copyright (C) 2010 - 2015 Board of Regents of the University of
6+
* Wisconsin-Madison.
7+
* %%
8+
* Redistribution and use in source and binary forms, with or without
9+
* modification, are permitted provided that the following conditions are met:
10+
*
11+
* 1. Redistributions of source code must retain the above copyright notice,
12+
* this list of conditions and the following disclaimer.
13+
* 2. Redistributions in binary form must reproduce the above copyright notice,
14+
* this list of conditions and the following disclaimer in the documentation
15+
* and/or other materials provided with the distribution.
16+
*
17+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
21+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27+
* POSSIBILITY OF SUCH DAMAGE.
28+
* #L%
29+
*/
30+
31+
package org.scijava.ui.swing.script;
32+
33+
import java.util.List;
34+
import java.util.Map;
35+
36+
import org.scijava.plugin.SciJavaPlugin;
37+
38+
/**
39+
* Base interface for auto-importer plugins.
40+
* <p>
41+
* A convenient, if sloppy, script editor feature inherited from the Fiji days
42+
* (where the script editor was developed originally) is the ability to use all
43+
* ImageJ 1.x classes without having to import them explicitly.
44+
* </p>
45+
* <p>
46+
* Nowadays, we support many more components than just the ImageJ 1.x classes,
47+
* and that feature is more a hindrance than a boon, but for
48+
* backwards-compatibility, we still support it. However, the script editor must
49+
* not depend on ImageJ 1.x any longer, hence we add support for AutoImporter
50+
* plugins that report which classes to auto-import.
51+
* </p>
52+
*
53+
* @author Johannes Schindelin
54+
*/
55+
public interface AutoImporter extends SciJavaPlugin {
56+
57+
Map<String, List<String>> getDefaultImports();
58+
59+
}
Lines changed: 200 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,200 @@
1+
/*
2+
* #%L
3+
* SciJava UI components for Java Swing.
4+
* %%
5+
* Copyright (C) 2010 - 2015 Board of Regents of the University of
6+
* Wisconsin-Madison.
7+
* %%
8+
* Redistribution and use in source and binary forms, with or without
9+
* modification, are permitted provided that the following conditions are met:
10+
*
11+
* 1. Redistributions of source code must retain the above copyright notice,
12+
* this list of conditions and the following disclaimer.
13+
* 2. Redistributions in binary form must reproduce the above copyright notice,
14+
* this list of conditions and the following disclaimer in the documentation
15+
* and/or other materials provided with the distribution.
16+
*
17+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
21+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27+
* POSSIBILITY OF SUCH DAMAGE.
28+
* #L%
29+
*/
30+
31+
package org.scijava.ui.swing.script;
32+
33+
import java.io.IOException;
34+
import java.io.PushbackReader;
35+
import java.io.Reader;
36+
import java.io.Writer;
37+
import java.util.Arrays;
38+
import java.util.Collection;
39+
import java.util.HashSet;
40+
import java.util.List;
41+
import java.util.Map.Entry;
42+
import java.util.Set;
43+
44+
import org.scijava.Context;
45+
import org.scijava.module.ModuleException;
46+
import org.scijava.plugin.PluginService;
47+
import org.scijava.script.ScriptLanguage;
48+
49+
/**
50+
* Generates the statements for the auto-imports (for internal use by the script
51+
* editor and script interpreter only).
52+
* <p>
53+
* This class generates import statements for the deprecated auto-import feature
54+
* of the script editor and prefixes the {@link Reader} with those statements.
55+
* </p>
56+
*
57+
* @author Johannes Schindelin
58+
*/
59+
public class DefaultAutoImporters {
60+
61+
private static Collection<AutoImporter> importers;
62+
63+
static Reader prefixAutoImports(final Context context,
64+
final ScriptLanguage language, final Reader reader, final Writer errors)
65+
throws ModuleException
66+
{
67+
final Object generator = getImportGenerator(context, language);
68+
if (generator == null) {
69+
try {
70+
errors.write("[WARNING] Auto-imports not available for language '" +
71+
(language == null ? "(null)" : language.getLanguageName()) + "'.\n");
72+
}
73+
catch (final IOException e) {
74+
throw new ModuleException(e);
75+
}
76+
return reader;
77+
}
78+
79+
try {
80+
errors.write("[WARNING] Auto-imports are active, but deprecated.\n");
81+
}
82+
catch (final IOException e) {
83+
throw new ModuleException(e);
84+
}
85+
86+
final String statements = generator.toString();
87+
88+
try {
89+
final PushbackReader result =
90+
new PushbackReader(reader, statements.length());
91+
result.unread(statements.toCharArray());
92+
return result;
93+
}
94+
catch (final IOException e) {
95+
throw new ModuleException(e);
96+
}
97+
}
98+
99+
public static Object getImportGenerator(final Context context,
100+
final ScriptLanguage language)
101+
{
102+
if (importers == null) {
103+
final PluginService pluginService =
104+
context.getService(PluginService.class);
105+
importers = pluginService.createInstancesOfType(AutoImporter.class);
106+
}
107+
108+
final String name = language == null ? null : language.getLanguageName();
109+
if ("Javascript".equalsIgnoreCase(name) || "ECMAScript".equals(name)) {
110+
return new DefaultImportStatements("importClass(Packages.", ");\n");
111+
}
112+
if ("Beanshell".equalsIgnoreCase(name)) {
113+
return new DefaultImportStatements("import ", ";\n");
114+
}
115+
if ("Ruby".equalsIgnoreCase(name)) {
116+
return new DefaultImportStatements("java_import '", "'\n");
117+
}
118+
if ("Python".equalsIgnoreCase(name)) {
119+
return new DefaultImportStatements(null, null) {
120+
121+
@Override
122+
public void generate(final StringBuilder builder,
123+
final String packageName, final List<String> classNames)
124+
{
125+
// Due to the construction (filtering duplicate names),
126+
// classNames can be empty
127+
if (classNames.size() == 0) return;
128+
129+
builder.append("from ").append(packageName).append(" import ");
130+
boolean first = true;
131+
for (final String className : classNames) {
132+
if (first) {
133+
first = false;
134+
}
135+
else {
136+
builder.append(", ");
137+
}
138+
builder.append(className);
139+
}
140+
builder.append("\n");
141+
}
142+
};
143+
}
144+
return null;
145+
}
146+
147+
private static interface ImportStatementGenerator {
148+
149+
void generate(StringBuilder builder, String packageName,
150+
List<String> classNames);
151+
152+
}
153+
154+
private static class DefaultImportStatements implements
155+
ImportStatementGenerator
156+
{
157+
158+
private final String prefix, suffix;
159+
private final Set<String> exclude;
160+
161+
DefaultImportStatements(final String prefix, final String suffix,
162+
final String... classNamesToExclude)
163+
{
164+
this.prefix = prefix;
165+
this.suffix = suffix;
166+
exclude = new HashSet<String>(Arrays.asList(classNamesToExclude));
167+
}
168+
169+
@Override
170+
public void generate(final StringBuilder builder, final String packageName,
171+
final List<String> classNames)
172+
{
173+
if ("java.lang".equals(packageName)) {
174+
return;
175+
}
176+
for (final String className : classNames) {
177+
if (exclude.contains(className)) continue;
178+
builder.append(prefix).append(packageName).append('.')
179+
.append(className).append(suffix);
180+
}
181+
}
182+
183+
@Override
184+
public String toString() {
185+
final StringBuilder builder = new StringBuilder();
186+
for (final AutoImporter importer : importers) {
187+
for (final Entry<String, List<String>> entry : importer
188+
.getDefaultImports().entrySet())
189+
{
190+
final String packageName = entry.getKey();
191+
final List<String> classNames = entry.getValue();
192+
generate(builder, packageName, classNames);
193+
}
194+
}
195+
return builder.toString();
196+
}
197+
198+
}
199+
200+
}

0 commit comments

Comments
 (0)