Skip to content

Commit f52d33d

Browse files
committed
Revamp this project as Script Editor plugins
This migrates all the Jython-specific Script Editor code here.
1 parent 803f549 commit f52d33d

15 files changed

Lines changed: 659 additions & 23 deletions

‎pom.xml‎

Lines changed: 37 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@
99
<relativePath />
1010
</parent>
1111

12-
<artifactId>jython-autocompletion</artifactId>
13-
<version>0.1.2-SNAPSHOT</version>
12+
<artifactId>script-editor-jython</artifactId>
13+
<version>0.1.0-SNAPSHOT</version>
1414

15-
<name>Jython Autocompletion</name>
16-
<description>Autocompletion for the Jython language in the Script Editor</description>
17-
<url>https://github.com/scijava/jython-autocompletion</url>
15+
<name>Jython Script Editor plugin</name>
16+
<description>Jython language support for SciJava Script Editor</description>
17+
<url>https://github.com/scijava/script-editor-jython</url>
1818
<inceptionYear>2020</inceptionYear>
1919
<organization>
2020
<name>SciJava</name>
@@ -75,6 +75,10 @@
7575
<url>https://imagej.net/people/imagejan</url>
7676
<properties><id>imagejan</id></properties>
7777
</contributor>
78+
<contributor>
79+
<name>Jonathan Hale</name>
80+
<properties><id>Squareys</id></properties>
81+
</contributor>
7882
</contributors>
7983

8084
<mailingLists>
@@ -85,18 +89,18 @@
8589
</mailingLists>
8690

8791
<scm>
88-
<connection>scm:git:git://github.com/scijava/jython-autocompletion</connection>
89-
<developerConnection>scm:git:git@github.com:scijava/jython-autocompletion</developerConnection>
92+
<connection>scm:git:git://github.com/scijava/script-editor-jython</connection>
93+
<developerConnection>scm:git:git@github.com:scijava/script-editor-jython</developerConnection>
9094
<tag>HEAD</tag>
91-
<url>https://github.com/scijava/jython-autocompletion</url>
95+
<url>https://github.com/scijava/script-editor-jython</url>
9296
</scm>
9397
<issueManagement>
9498
<system>GitHub Issues</system>
95-
<url>https://github.com/scijava/jython-autocompletion/issues</url>
99+
<url>https://github.com/scijava/script-editor-jython/issues</url>
96100
</issueManagement>
97101
<ciManagement>
98102
<system>GitHub Actions</system>
99-
<url>https://github.com/scijava/jython-autocompletion/actions</url>
103+
<url>https://github.com/scijava/script-editor-jython/actions</url>
100104
</ciManagement>
101105

102106
<properties>
@@ -107,8 +111,10 @@
107111
<!-- NB: Deploy releases to the SciJava Maven repository. -->
108112
<releaseProfiles>sign,deploy-to-scijava</releaseProfiles>
109113

110-
<script-editor.version>0.5.12</script-editor.version>
111114
<antlr-runtime.version>3.5.2</antlr-runtime.version>
115+
116+
<!-- TEMP: Until pom-scijava 32.0.0 is released and used here. -->
117+
<script-editor.version>0.5.12</script-editor.version>
112118
</properties>
113119

114120
<dependencies>
@@ -117,11 +123,24 @@
117123
<groupId>org.scijava</groupId>
118124
<artifactId>script-editor</artifactId>
119125
</dependency>
126+
<dependency>
127+
<groupId>org.scijava</groupId>
128+
<artifactId>scijava-common</artifactId>
129+
</dependency>
130+
120131
<!-- Third-party dependencies -->
121132
<dependency>
122133
<groupId>com.fifesoft</groupId>
123134
<artifactId>autocomplete</artifactId>
124135
</dependency>
136+
<dependency>
137+
<groupId>com.fifesoft</groupId>
138+
<artifactId>languagesupport</artifactId>
139+
</dependency>
140+
<dependency>
141+
<groupId>com.fifesoft</groupId>
142+
<artifactId>rsyntaxtextarea</artifactId>
143+
</dependency>
125144
<dependency>
126145
<groupId>org.antlr</groupId>
127146
<artifactId>antlr-runtime</artifactId>
@@ -131,6 +150,13 @@
131150
<groupId>org.python</groupId>
132151
<artifactId>jython-slim</artifactId>
133152
</dependency>
153+
154+
<!-- Runtime dependencies -->
155+
<dependency>
156+
<groupId>org.scijava</groupId>
157+
<artifactId>scripting-jython</artifactId>
158+
<scope>runtime</scope>
159+
</dependency>
134160
</dependencies>
135161

136162
<repositories>

src/main/java/org/scijava/jython/autocompletion/ClassDotAutocompletions.java renamed to src/main/java/org/scijava/plugins/scripteditor/jython/ClassDotAutocompletions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
* <http://www.gnu.org/licenses/gpl-3.0.html>.
2020
* #L%
2121
*/
22-
package org.scijava.jython.autocompletion;
22+
package org.scijava.plugins.scripteditor.jython;
2323

2424
import java.util.ArrayList;
2525
import java.util.List;

src/main/java/org/scijava/jython/autocompletion/DefVarDotAutocompletions.java renamed to src/main/java/org/scijava/plugins/scripteditor/jython/DefVarDotAutocompletions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
* <http://www.gnu.org/licenses/gpl-3.0.html>.
2020
* #L%
2121
*/
22-
package org.scijava.jython.autocompletion;
22+
package org.scijava.plugins.scripteditor.jython;
2323

2424
import java.util.List;
2525

src/main/java/org/scijava/jython/autocompletion/DotAutocompletions.java renamed to src/main/java/org/scijava/plugins/scripteditor/jython/DotAutocompletions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
* <http://www.gnu.org/licenses/gpl-3.0.html>.
2020
* #L%
2121
*/
22-
package org.scijava.jython.autocompletion;
22+
package org.scijava.plugins.scripteditor.jython;
2323

2424
import java.lang.reflect.Field;
2525
import java.lang.reflect.Method;

src/main/java/org/scijava/jython/autocompletion/EmptyDotAutocompletions.java renamed to src/main/java/org/scijava/plugins/scripteditor/jython/EmptyDotAutocompletions.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
* <http://www.gnu.org/licenses/gpl-3.0.html>.
2020
* #L%
2121
*/
22-
package org.scijava.jython.autocompletion;
22+
package org.scijava.plugins.scripteditor.jython;
2323

2424
import java.util.Collections;
2525
import java.util.List;
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
/*-
2+
* #%L
3+
* Script Editor and Interpreter for SciJava script languages.
4+
* %%
5+
* Copyright (C) 2009 - 2022 SciJava developers.
6+
* %%
7+
* Redistribution and use in source and binary forms, with or without
8+
* modification, are permitted provided that the following conditions are met:
9+
*
10+
* 1. Redistributions of source code must retain the above copyright notice,
11+
* this list of conditions and the following disclaimer.
12+
* 2. Redistributions in binary form must reproduce the above copyright notice,
13+
* this list of conditions and the following disclaimer in the documentation
14+
* and/or other materials provided with the distribution.
15+
*
16+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19+
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
20+
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21+
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22+
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23+
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24+
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25+
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26+
* POSSIBILITY OF SUCH DAMAGE.
27+
* #L%
28+
*/
29+
package org.scijava.plugins.scripteditor.jython;
30+
31+
import java.util.HashMap;
32+
import java.util.regex.Matcher;
33+
import java.util.regex.Pattern;
34+
35+
import javax.swing.text.BadLocationException;
36+
37+
import org.fife.ui.autocomplete.AutoCompletion;
38+
import org.fife.ui.autocomplete.Completion;
39+
import org.fife.ui.autocomplete.CompletionProvider;
40+
import org.scijava.ui.swing.script.EditorPane;
41+
import org.scijava.ui.swing.script.autocompletion.ImportCompletion;
42+
43+
public class JythonAutoCompletion extends AutoCompletion {
44+
45+
public JythonAutoCompletion(final CompletionProvider provider) {
46+
super(provider);
47+
this.setShowDescWindow(true);
48+
}
49+
50+
static private final Pattern importPattern = Pattern.compile("^(from[ \\t]+([a-zA-Z_][a-zA-Z0-9._]*)[ \\t]+|)import[ \\t]+([a-zA-Z_][a-zA-Z0-9_]*[ \\ta-zA-Z0-9_,]*)[ \\t]*([\\\\]*|)[ \\t]*(#.*|)$"),
51+
tripleQuotePattern = Pattern.compile("\"\"\""),
52+
variableDeclarationPattern = Pattern.compile("([a-zA-Z_][a-zA-Z0-9._]*)[ \\t]*=[ \\t]*([A-Z_][a-zA-Z0-9._]*)(?:\\()"); // E.g., in 'imp=ImagePlus()' group1: imp; group2: ImagePlus
53+
54+
static public class Import {
55+
final public String className,
56+
alias; // same as simple class name, or the alias from "as <alias>"
57+
final public int lineNumber;
58+
59+
public Import(final String className, final String alias, final int lineNumber) {
60+
this.className = className;
61+
this.alias = null != alias ? alias : className.substring(className.lastIndexOf('.') + 1);
62+
this.lineNumber = lineNumber;
63+
}
64+
65+
// E.g. handle "ImageJFunctions as IL" -> ["ImageJFunctions", "as", "IL"]
66+
public Import(final String packageName, final String[] parts, final int lineNumber) {
67+
this(packageName + "." + parts[0], 3 == parts.length ? parts[2] : null, lineNumber);
68+
}
69+
}
70+
71+
static public final String findClassAliasOfVariable(final String variable, String inputText) {
72+
final String[] lines = inputText.split("\n");
73+
for (int i = 0; i < lines.length; ++i) {
74+
final String line = lines[i];
75+
final Matcher matcher = variableDeclarationPattern.matcher(line);
76+
if (matcher.find()) {
77+
// a line containing a variable declaration
78+
// System.out.println("Queried variable: " + variable);
79+
// System.out.println("Hit: line #" + i + ": " + line);
80+
// System.out.println("Matcher g1: " + matcher.group(1));
81+
// System.out.println("Matcher g2: " + matcher.group(2));
82+
if (variable.equals(matcher.group(1))) {
83+
return matcher.group(2);
84+
}
85+
}
86+
}
87+
return null;
88+
}
89+
90+
static public final HashMap<String, Import> findImportedClasses(final String text) {
91+
final HashMap<String, Import> importedClasses = new HashMap<>();
92+
String packageName = "";
93+
boolean endingBackslash = false;
94+
boolean insideTripleQuotes = false;
95+
96+
// Scan the whole file for imports
97+
final String[] lines = text.split("\n");
98+
for (int i=0; i<lines.length; ++i) {
99+
String line = lines[i];
100+
final String trimmed = line.trim();
101+
if (0 == trimmed.length() || '#' == trimmed.charAt(0)) continue;
102+
final Matcher mq = tripleQuotePattern.matcher(line);
103+
int n_triple_quotes = 0;
104+
while (mq.find()) ++n_triple_quotes;
105+
if (insideTripleQuotes) {
106+
if (0 != n_triple_quotes % 2) { // odd number
107+
insideTripleQuotes = false;
108+
}
109+
continue;
110+
} else {
111+
// If odd, enter
112+
if (0 != n_triple_quotes % 2) {
113+
insideTripleQuotes = true;
114+
continue;
115+
}
116+
}
117+
// Handle classes imported in a truncated import statement
118+
if (endingBackslash) {
119+
String importLine = line;
120+
final int backslash = line.lastIndexOf('\\');
121+
if (backslash > -1) importLine = importLine.substring(0, backslash);
122+
else {
123+
final int sharp = importLine.lastIndexOf('#');
124+
if (sharp > -1) importLine = importLine.substring(0, sharp);
125+
}
126+
for (final String simpleClassName : importLine.split(",")) {
127+
final Import im = new Import(packageName, simpleClassName.trim().split("\\s"), i);
128+
importedClasses.put(im.alias, im);
129+
}
130+
endingBackslash = -1 != backslash; // otherwise there is another line with classes of the same package
131+
continue;
132+
}
133+
final Matcher m = importPattern.matcher(line);
134+
if (m.find()) {
135+
packageName = null == m.group(2) ? "" : m.group(2);
136+
for (final String simpleClassName : m.group(3).split(",")) {
137+
final Import im = new Import(packageName, simpleClassName.trim().split("\\s"), i);
138+
importedClasses.put(im.alias, im);
139+
}
140+
endingBackslash = null != m.group(4) && m.group(4).length() > 0 && '\\' == m.group(4).charAt(0);
141+
}
142+
}
143+
144+
return importedClasses;
145+
}
146+
147+
@Override
148+
protected void insertCompletion(final Completion c, final boolean typedParamListStartChar) {
149+
if (c instanceof ImportCompletion) {
150+
final EditorPane editor = (EditorPane) super.getTextComponent();
151+
editor.beginAtomicEdit();
152+
try {
153+
super.insertCompletion(c, typedParamListStartChar);
154+
final ImportCompletion cc = (ImportCompletion)c;
155+
final HashMap<String, Import> importedClasses = findImportedClasses(editor.getText());
156+
// Insert import statement after the last import, if not there already
157+
for (final Import im : importedClasses.values()) {
158+
if (im.className.contentEquals(cc.getClassName()))
159+
return; // don't insert
160+
}
161+
try {
162+
final int insertAtLine = 0 == importedClasses.size() ? 0
163+
: importedClasses.values().stream().map(im -> im.lineNumber).reduce(Math::max).get();
164+
editor.insert(cc.getImportStatement() + "\n", editor.getLineStartOffset(0 == insertAtLine ? 0 : insertAtLine + 1));
165+
} catch (BadLocationException e) {
166+
e.printStackTrace();
167+
}
168+
} finally {
169+
editor.endAtomicEdit();
170+
}
171+
} else {
172+
super.insertCompletion(c, typedParamListStartChar);
173+
}
174+
}
175+
}

src/main/java/org/scijava/jython/autocompletion/JythonAutoCompletions.java renamed to src/main/java/org/scijava/plugins/scripteditor/jython/JythonAutoCompletions.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
* <http://www.gnu.org/licenses/gpl-3.0.html>.
2020
* #L%
2121
*/
22-
package org.scijava.jython.autocompletion;
22+
package org.scijava.plugins.scripteditor.jython;
2323

2424
import java.io.File;
2525
import java.io.IOException;
@@ -42,7 +42,6 @@
4242
import org.fife.ui.autocomplete.CompletionProvider;
4343
import org.python.indexer.types.NModuleType;
4444
import org.scijava.ui.swing.script.autocompletion.AutoCompletionListener;
45-
import org.scijava.ui.swing.script.autocompletion.JythonAutocompletionProvider;
4645

4746
public class JythonAutoCompletions implements AutoCompletionListener
4847
{

0 commit comments

Comments
 (0)