Skip to content

Commit ae49831

Browse files
committed
Allow jarified files to be loaded in the script editor.
1 parent 5891bb8 commit ae49831

20 files changed

+942
-0
lines changed
+124
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
/*
2+
* IJ BAR: https://github.com/tferr/Scripts
3+
*
4+
* This program is free software; you can redistribute it and/or modify it under the terms of the
5+
* GNU General Public License as published by the Free Software Foundation
6+
* (http://www.gnu.org/licenses/gpl.txt).
7+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
8+
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
9+
* General Public License for more details.
10+
*/
11+
package bar.plugin;
12+
13+
import java.io.IOException;
14+
import java.net.URI;
15+
import java.net.URISyntaxException;
16+
import java.net.URL;
17+
import java.nio.file.FileSystem;
18+
import java.nio.file.FileSystems;
19+
import java.nio.file.Files;
20+
import java.nio.file.Path;
21+
import java.nio.file.PathMatcher;
22+
import java.nio.file.Paths;
23+
import java.util.ArrayList;
24+
import java.util.Collections;
25+
import java.util.Iterator;
26+
import java.util.stream.Stream;
27+
28+
import net.imagej.ImageJ;
29+
30+
import org.scijava.Context;
31+
import org.scijava.app.StatusService;
32+
import org.scijava.command.Command;
33+
import org.scijava.plugin.Parameter;
34+
import org.scijava.plugin.Plugin;
35+
import org.scijava.ui.DialogPrompt;
36+
import org.scijava.ui.UIService;
37+
import org.scijava.ui.swing.script.TextEditor;
38+
39+
/** Loads a new instance of the Script editor with jarified tutorial files */
40+
@Plugin(type = Command.class, headless = true, menuPath = "BAR > Snippets > Tutorials...")
41+
public class Tutorials implements Command {
42+
43+
@Parameter
44+
private Context context;
45+
46+
@Parameter
47+
private UIService uiService;
48+
49+
@Parameter
50+
private StatusService statusService;
51+
52+
@Parameter(label = "Which introductory tutorial?", choices = { "Python", "BeanShell" })
53+
private String lang;
54+
55+
@Override
56+
public void run() {
57+
final ArrayList<URL> urls = getTutorialFiles(lang);
58+
if (urls == null || urls.isEmpty()) {
59+
uiService.showDialog("Could not load tutorial files.", DialogPrompt.MessageType.ERROR_MESSAGE);
60+
return;
61+
}
62+
final TextEditor editor = new TextEditor(context);
63+
for (final URL url : urls) {
64+
statusService.showStatus(urls.indexOf(url), urls.size(), "Opening tutorial files...");
65+
editor.loadTemplate(url);
66+
}
67+
editor.switchTo(0);
68+
editor.setVisible(true);
69+
editor.setTitle("BAR Tutorial Files [" + lang + "]");
70+
statusService.clearStatus();
71+
}
72+
73+
private String getMatcherPattern(final String language) {
74+
// see http://docs.oracle.com/javase/tutorial/essential/io/find.html
75+
switch (language.toLowerCase()) {
76+
case "python":
77+
return "glob:**.py";
78+
case "beanshell":
79+
return "glob:**.bsh";
80+
case "groovy":
81+
return "glob:**.{groovy,gvy}";
82+
default:
83+
return "glob:**.*"; // any extension
84+
}
85+
}
86+
87+
/* See http://stackoverflow.com/a/28057735 for details */
88+
private ArrayList<URL> getTutorialFiles(final String language) {
89+
final String dir = "/tutorials";
90+
final ArrayList<URL> urlList = new ArrayList<>();
91+
final PathMatcher matcher = FileSystems.getDefault().getPathMatcher(getMatcherPattern(language));
92+
try {
93+
final URI uri = Tutorials.class.getResource(dir).toURI();
94+
FileSystem fileSystem = null;
95+
Path path;
96+
if ("jar".equals(uri.getScheme())) {
97+
fileSystem = FileSystems.newFileSystem(uri, Collections.<String, Object>emptyMap());
98+
path = fileSystem.getPath(dir);
99+
} else {
100+
path = Paths.get(uri);
101+
}
102+
final Stream<Path> walk = Files.walk(path, 1);
103+
final Iterator<Path> it = walk.iterator();
104+
while (it.hasNext()) {
105+
final Path p = it.next();
106+
if (matcher.matches(p)) {
107+
urlList.add(p.toUri().toURL());
108+
}
109+
}
110+
walk.close();
111+
if (fileSystem != null)
112+
fileSystem.close();
113+
} catch (IOException | URISyntaxException exc) {
114+
return null;
115+
}
116+
return urlList;
117+
}
118+
119+
public static void main(final String... args) {
120+
final ImageJ ij = net.imagej.Main.launch(args);
121+
ij.command().run(Tutorials.class, true);
122+
}
123+
124+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* BeanShell01.bsh
3+
* IJ BAR: https://github.com/tferr/Scripts#scripts
4+
* *************************************************
5+
* 1. Basics
6+
* *************************************************
7+
*/
8+
9+
// BeanShell (bsh) is "no-frills Java" and inherits all of Java
10+
// basic syntax. You can actually mix Java code with bsh and
11+
// the BeanShell interpreter will recognize all of it (with
12+
// some minor subtleties, we will discuss later on). Conversely,
13+
// converting BeanShell into Java is quite straightforward.
14+
// Here are some basics:
15+
16+
// This is a comment (typically single line)
17+
/* This is also a comment (typically multi-line) */
18+
19+
// BeanShell features a built-in print command that outputs to
20+
// the Script Editor's console ("Show Output" button). It
21+
// accepts only one argument (a string, number, object, ...).
22+
// BTW, Note that in Java and in BeanShell, every statement
23+
// must end in a semicolon:
24+
print("Line 24: " + "Hello!"); // A concatenated string
25+
26+
// Math works as expected:
27+
a = 1+1; // Sum
28+
b = 2*4; // Multiplication
29+
c = Math.pow(2,4); // Exponentiation (2^14 = 16)
30+
print("Line 30: "+ a + "," + b + "," + c);
31+
32+
// Division is slightly special:
33+
print("Line 33:" + "Integer division: 3/4=" + 3/4);
34+
print("Line 34:" + "Float division: 3/4=" + 3.0/4);
35+
36+
// Note that, as in Python, variables may be dynamically typed:
37+
d = 1;
38+
print("Line 38: " + "d is a number: " + d);
39+
d = "the 4th letter in the alphabet";
40+
print("Line 40: " + "but now d is a string: " + d);
41+
42+
// Operators:
43+
print("Line 43: " + "a equals b: " + (a == b) );
44+
print("Line 44: " + "a is not equal to b: " + (a != b) );
45+
print("Line 45: " + "a is not equal to b: " + !(a == b) );
46+
print("Line 46: " + "a greater than b: " + (a > b) );
47+
print("Line 47: " + "a is greater or equal to b: " + (a >= b) );
48+
49+
// To know more: http://www.beanshell.org/manual/contents.html
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/**
2+
* BeanShell02.bsh
3+
* IJ BAR: https://github.com/tferr/Scripts#scripts
4+
* *************************************************
5+
* 2. If statements, for loops and switch statements
6+
* *************************************************
7+
*/
8+
9+
a = 10; b = 20; // Semicolon separating in-line statements
10+
11+
// An if statement:
12+
if (a == b) {
13+
print("Line 13: " + "a is b!");
14+
} else if (a < b) {
15+
print("Line 15: " + "a is smaller than b!");
16+
} else if (a<b) {
17+
print("Line 17: " + "a is greater than b!");
18+
} else {
19+
print("Line 19: "
20+
+ "This is never evaluated because previous conditions"
21+
+ "cover all posiibilities");
22+
}
23+
24+
// A for loop is used to iterate over collections (lists) and arrays.
25+
// So we'll have a look at arrays before looking into for loops.
26+
// Arrays are fixed-size collections of elements of the same type
27+
// (e.g., an array holding strings can not hold integers). So we need
28+
// to specify the array data type when declaring one. This is how we
29+
// define arrays with pre-filled values:
30+
int[] intArray = { 1, 2, 3 };
31+
String[] stringArray = {"One", "Two", "Three"};
32+
33+
// We can also declare an empty array and populate it later on
34+
intArray = new int[3]; // Integer in square brackets specifies array size
35+
36+
// To populate it, we use the assignment operator (=) to fill one item
37+
// at a time. As mentioned before, arrays are indexed sequences of
38+
// items. Java (and thus, BeanShell) uses zero-based arrays: The 1st
39+
// index (item position) is zero, the 2nd index is one, etc. This is
40+
// how we would fill the array "manually":
41+
intArray[0] = 1; // Assign "1" to indexed position 0 (1st position)
42+
intArray[1] = 2; // Assign "2" to indexed position 1 (2nd position)
43+
intArray[2] = 3; // etc.
44+
45+
// This works fine unless the array is large. In such situations, we
46+
// can use a "for loop" that "fills" the array by iterating through
47+
// the array positions (indices). We use <length> (a property of
48+
// array objects) to determine the size of the array (how many
49+
// positions it has):
50+
intArray = new int[3];
51+
print("Line 51: "+ "Contents of intArray:");
52+
for (i=0; i<intArray.length; i++) {
53+
intArray[i] = i + 1;
54+
print(" Line 54 (for loop): intArray["+ i + "] = " + intArray[i]);
55+
}
56+
57+
// We can also loop through arrays using what is called an "enhanced
58+
// for loop". Here is an example:
59+
print("Line 59: "+ "Contents of intArray:");
60+
for (item : intArray) {
61+
print(" Line 61 (enhanced for loop): "+ item);
62+
}
63+
64+
65+
// Switch statements are a special kind of if-else statements with
66+
// multiple execution paths. Here is an example:
67+
cocktail = "cuba libre";
68+
switch (cocktail) {
69+
case "margarita":
70+
print("Line 70: cocktail has tequilla");
71+
break;
72+
case "martini":
73+
case "gin and tonic":
74+
print("Line 74: cocktail has gin");
75+
break;
76+
case "cuba libre":
77+
print("Line 77: cocktail has rum");
78+
break;
79+
default: // Any value not caught_above
80+
print("Line 80: I'm not aware of the specified cocktail");
81+
}
82+
83+
// BTW, While Java switch statements are restricted to certain data
84+
// types (an integer, a character, or a string) in BeanShell switch
85+
// statements apply to any object. Neat hm?
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/**
2+
* BeanShell03.bsh
3+
* IJ BAR: https://github.com/tferr/Scripts#scripts
4+
* *************************************************
5+
* 3. Imports statements
6+
* *************************************************
7+
*/
8+
9+
// Importing classes from Java packages works exactly
10+
// as in Java, but in a more flexible way since import
11+
// statements can occur anywhere in a script:
12+
import java.lang.Math;
13+
print("Line 13: PI="+ Math.PI); // http://javadoc.imagej.net/Java7/index.html?java/lang/Math.html
14+
15+
// Importing the class IJ in the ij package
16+
import ij.IJ;
17+
print("Line 17: We're running IJ" + IJ.getVersion()); //http://javadoc.imagej.net/ImageJ1/index.html?ij/IJ.html
18+
19+
// As in Java, we can also specify the fully qualified
20+
// class name without an import declaration as long as
21+
// ImageJ is aware of it, i.e., the class is in our
22+
// CLASSPATH[1]. Here is an example:
23+
print("Line 23: We're running IJ" + ij.IJ.getVersion()); //http://javadoc.imagej.net/ImageJ1/index.html?ij/IJ.html
24+
25+
// [1] https://en.wikipedia.org/wiki/Classpath_(Java)
26+
// To know more: http://www.beanshell.org/manual/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/**
2+
* BeanShell04.bsh
3+
* IJ BAR: https://github.com/tferr/Scripts#scripts
4+
* *************************************************
5+
* 4. Methods and the super keyword
6+
* *************************************************
7+
*/
8+
9+
// BeanShell methods ("Java functions") are defined as
10+
// in Java, with return values specified by a <return>
11+
// statement. Bsh methods allow dynamic (loose) of both
12+
// arguments and return types. We will come back to this
13+
// in a second. Meanwhile, here is an example of a
14+
// method that takes no arguments:
15+
16+
/** This method returns a string of today's date */
17+
today() {
18+
import java.util.Date; // http://javadoc.imagej.net/Java7/index.html?java/util/Date.html
19+
date = new Date();
20+
return date.toString(); // http://javadoc.imagej.net/Java7/index.html?java/lang/Object.html#toString--
21+
}
22+
23+
print("Line 23: today() returned" + today());
24+
25+
26+
// A Method with arguments:
27+
/**
28+
* This method returns the smallest of two arguments, and is a
29+
* kludged assembly of Java.lang.Math.min(), see
30+
* http://javadoc.imagej.net/Java7/index.html?java/lang/Math.html
31+
*/
32+
minMethod(a, b) {
33+
if (a < b) {
34+
return a;
35+
} else {
36+
return b;
37+
}
38+
}
39+
40+
print("Line 40: " + minMethod(10,20) + "is smaller");
41+
42+
43+
// We can also specify argument and/or return types:
44+
/** This method sums only integers */
45+
int intSum(int a, int b) {
46+
return a + b;
47+
}
48+
49+
print("Line 49: The sum of 2 integers: " + intSum(2,4) );
50+
51+
// void methods do not return any value:
52+
void voidMethod() {
53+
print("I return nothing. I just print stuff.");
54+
}
55+
print("Line 55: " + voidMethod());
56+
57+
58+
// Now let's have a look at "Global variables":
59+
// It is possible to explicitly refer to a declared variable
60+
// (or method) defined outside the scope of a method using
61+
// the <super> keyword, similarly to Python's <global>
62+
// keyword (Python04.py tutorial). Example:
63+
int variable = 2;
64+
myMethod() {
65+
int variable = 40;
66+
print("Line 66: Inside the method, variable= " + variable);
67+
print("Line 67: Outside the method, variable= " + super.variable);
68+
// Note that this would not work for loosely declared variables
69+
// What happens when one does not specify the variable data type?
70+
}
71+
myMethod();
72+
73+
// To know more: http://www.beanshell.org/manual/
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* BeanShell05-1.bsh
3+
* IJ BAR: https://github.com/tferr/Scripts#scripts
4+
* *************************************************
5+
* 5.1 Scripting using BAR libs I
6+
* *************************************************
7+
*/
8+
9+
// BAR libs (stored in the /BAR/lib/ directory) are
10+
// centralized libraries (BeanShell, IJM and Python,
11+
// etc.) that can be shared across files.
12+
// "BAR>Snippets>New Snippet..." exemplifies how to
13+
// use the main BeanShell lib distributed with BAR.
14+
//
15+
// Let's create a new snippet and run "BAR>lib>Reveal
16+
// /lib" so that we can browse lib files. If you press
17+
// <<Run>>, I'll run the commands for you:
18+
19+
import ij.IJ;
20+
IJ.run("Reveal /lib", "");
21+
IJ.run("New Snippet...");
22+
23+
24+
// Further reading:
25+
// BAR>lib>lib Help... and http://imagej.net/BAR#BAR_lib

0 commit comments

Comments
 (0)