Auto code completion for IJ macro

imagej
macro
auto-completion

#1

Hey IJ macro fans,

I just implemented auto completion and online help for ImageJ macro in the script editor. I think that’s quite useful. Or at least I would have loved to have it when I started with macro programming. It’s basic but functional, as you can see here:

However, before creating a PR, I was hoping for some help from the community for testing the features. Thus, if some of you find some time, please [download the JAR file from here],
(https://cloud.mpi-cbg.de/index.php/s/4Wcj5Pev401kVqT) and this JAR and also this JAR and put them in the jars directory of your Fiji installation (and remove any older version). Btw the source is also available on github.

Would be interesting to know what others think/observe:

  • Does it work on all operating systems?
  • Is the blinking autocompletion pulldown too annoying?
  • Does it harm pre-existing workflows or short cuts?

Thanks!

Cheers,
Robert


#2

Hi, that’s excellent. Will test. Thanks


#3

Fantastic project, Robert - I would have loved to have this as well.

Unfortunately, it’s not working for my system. I’m unable to launch the script editor at all, much less test your new autocompletion feature. Let me know if you have suggestions and want me to try again!

After downloading script-editor-0.2.1-SNAPSHOT.jar, adding it to my Fiji jars folder and removing the existing script-editor-0.1.6.jar, attempting to launch the script editor (with either the menu commands or the hotkey shortcut [) produces this error:

(Fiji Is Just) ImageJ 2.0.0-rc-67/1.52d; Java 1.8.0_66 [64-bit]; Mac OS X 10.13.5; 83MB of 8889MB (<1%)
 
java.lang.RuntimeException: java.util.concurrent.ExecutionException: java.lang.NullPointerException
	at net.imagej.legacy.LegacyService.runLegacyCompatibleCommand(LegacyService.java:303)
	at net.imagej.legacy.DefaultLegacyHooks.interceptRunPlugIn(DefaultLegacyHooks.java:163)
	at ij.IJ.runPlugIn(IJ.java)
	at ij.Executer.runCommand(Executer.java:137)
	at ij.Executer.run(Executer.java:66)
	at java.lang.Thread.run(Thread.java:745)
Caused by: java.util.concurrent.ExecutionException: java.lang.NullPointerException
	at java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
	at net.imagej.legacy.LegacyService.runLegacyCompatibleCommand(LegacyService.java:299)
	... 5 more
Caused by: java.lang.NullPointerException
	at org.scijava.ui.swing.script.TextEditor.loadPreferences(TextEditor.java:732)
	at org.scijava.ui.swing.script.TextEditor.<init>(TextEditor.java:233)
	at org.scijava.ui.swing.script.ScriptEditor.run(ScriptEditor.java:55)
	at org.scijava.command.CommandModule.run(CommandModule.java:199)
	at org.scijava.module.ModuleRunner.run(ModuleRunner.java:168)
	at org.scijava.module.ModuleRunner.call(ModuleRunner.java:127)
	at org.scijava.module.ModuleRunner.call(ModuleRunner.java:66)
	at org.scijava.thread.DefaultThreadService$3.call(DefaultThreadService.java:238)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
	... 1 more

Mac High Sierra, 10.13.5

Fiji version: 2.0.0-rc-67/1.52d
Build 1762a07c5c
Date: 2018-06-04T18:22:47+0000

$ java -version
java version "1.8.0_144"
Java(TM) SE Runtime Environment (build 1.8.0_144-b01)
Java HotSpot(TM) 64-Bit Server VM (build 25.144-b01, mixed mode)

#4

Hi @GenevieveBuckley,

thanks for the feedback. I think I found the issue. Could you please also download this file and put it in the jars dir:

Source is also available here.

And maybe one of the core developers (@ctrueden ? @imagejan ? ) may tell me, why the new script-editor.jar needs the batch-processor.jar which is apparently not part of ImageJs distribution? The issue is not obvious to me… I guess somebody was about to implement something in the script-editor and did not finish. That may also explain why you replaced version 1.6.0 with 2.1.0-SNAPSHOT. That’s quite a little jump :wink:

Thanks again!

Cheers,
Robert


#5

A new dependency to the SciJava batch-processor project has been introduced with this commit:

… which adds a Batch button to the script editor interface.

It will be part of the official distribution and is supposed to be shipped with the next release of Fiji components (which @ctrueden planned for this week or so (?), but was waiting for me to have time to update the documentation on https://imagej.net/Batch).

But if you base your work on the latest master branch of script-editor, you’ll have to either rely on Maven to install the dependency for you, or install it manually.

Yes, according to semantic versioning (SemVer), the major version needed to be increased with this change.

No need to share it via the MPI-CBG cloud; the official release of batch-processor.jar is available via Maven here:

http://maven.imagej.net/service/local/repositories/releases/content/org/scijava/batch-processor/0.1.1/batch-processor-0.1.1.jar


Thanks a lot for your work, @haesleinhuepf! It would be great if you submit a PR (which doesn’t preclude the option to still make changes after people in the community had a chance to test).


#6

Hi @imagejan,

Alright, here you go:

Cheers,
Robert


#7

Awesome feature :heart:

Autocompletion shows up on Xubuntu 17.10.

I tried the same example (Process_Folder.ijm) and a few things are a bit irritating - what do the dash signs symbolize? Also if there are two dashes and I hit enter, one dash will be appended to the autocompleted code. Not sure if this is intended.

Also I cannot autocomplete any object related functions, I understand that this may be way too complex, but as soon as I type input. and want to autocomplete it acts as if I am in a new line. For example, IJ is autocompleted with all the IJ1 functions but IJ. is completely ignored. Do you know what I mean? Can this be prevented somehow?

EDIT I also got this error when I opened the editor.

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
	at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
	at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
	at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
	at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
	at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1513)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
	at java.net.URL.openStream(URL.java:1038)
	at org.scijava.ui.swing.script.languagesupport.MacroAutoCompletionProvider.parseFunctionsHtmlDoc(MacroAutoCompletionProvider.java:48)
	at org.scijava.ui.swing.script.languagesupport.MacroAutoCompletionProvider.<init>(MacroAutoCompletionProvider.java:29)
	at org.scijava.ui.swing.script.languagesupport.MacroAutoCompletionProvider.getInstance(MacroAutoCompletionProvider.java:37)
	at org.scijava.ui.swing.script.languagesupport.MacroLanguageSupportPlugin.install(MacroLanguageSupportPlugin.java:42)
	at org.scijava.ui.swing.script.EditorPane.setLanguage(EditorPane.java:519)
	at org.scijava.ui.swing.script.TextEditor.setLanguage(TextEditor.java:1604)
	at org.scijava.ui.swing.script.TextEditor$9.actionPerformed(TextEditor.java:491)
	at javax.swing.AbstractButton.fireActionPerformed(AbstractButton.java:2022)
	at javax.swing.AbstractButton$Handler.actionPerformed(AbstractButton.java:2348)
	at javax.swing.DefaultButtonModel.fireActionPerformed(DefaultButtonModel.java:402)
	at javax.swing.JToggleButton$ToggleButtonModel.setPressed(JToggleButton.java:308)
	at javax.swing.AbstractButton.doClick(AbstractButton.java:376)
	at javax.swing.plaf.basic.BasicMenuItemUI.doClick(BasicMenuItemUI.java:833)
	at javax.swing.plaf.basic.BasicMenuItemUI$Handler.mouseReleased(BasicMenuItemUI.java:877)
	at java.awt.Component.processMouseEvent(Component.java:6535)
	at javax.swing.JComponent.processMouseEvent(JComponent.java:3324)
	at java.awt.Component.processEvent(Component.java:6300)
	at java.awt.Container.processEvent(Container.java:2236)
	at java.awt.Component.dispatchEventImpl(Component.java:4891)
	at java.awt.Container.dispatchEventImpl(Container.java:2294)
	at java.awt.Component.dispatchEvent(Component.java:4713)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4888)
	at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4525)
	at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4466)
	at java.awt.Container.dispatchEventImpl(Container.java:2280)
	at java.awt.Window.dispatchEventImpl(Window.java:2750)
	at java.awt.Component.dispatchEvent(Component.java:4713)
	at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:758)
	at java.awt.EventQueue.access$500(EventQueue.java:97)
	at java.awt.EventQueue$3.run(EventQueue.java:709)
	at java.awt.EventQueue$3.run(EventQueue.java:703)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:86)
	at java.awt.EventQueue$4.run(EventQueue.java:731)
	at java.awt.EventQueue$4.run(EventQueue.java:729)
	at java.security.AccessController.doPrivileged(Native Method)
	at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(ProtectionDomain.java:76)
	at java.awt.EventQueue.dispatchEvent(EventQueue.java:728)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:201)
	at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:116)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:105)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:101)
	at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:93)
	at java.awt.EventDispatchThread.run(EventDispatchThread.java:82)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
	at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:230)
	at sun.security.validator.Validator.validate(Validator.java:260)
	at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
	at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
	at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491)
	... 58 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:146)
	at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
	at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
	... 64 more

#8

Hey @frauzufall,

thanks for testing!

  • I removed the dashes (they are intended to divide between command and short description, but there is no short description).
  • I’m now catching the SSL exception (which doesn’t happen on my machine). Btw. it accesses the internet once, because the list of suggestions is generated from this website:
    https://imagej.net/developer/macro/functions.html
  • The auto-completion behind input. cannot be object related, because there are no real objects in IJ macro. The only pseudo-objects are things like IJ, Array, Table and so on. Changing the pulldown content behind IJ. would require changes in upstream dependencies. However, the pulldown is supposed to open automatically after entering IJ without dot. Let me think a bit about it. I’ll see what I can do.

Whoever want’s to test the new version, needs to download and install three JARS now :smile: : script-editor, imagej-legacy and batch-processor

Thanks again for the support! (Also to @ctrueden who helps coding behind the scenes )

Cheers,
Robert


#9

@haesleinhuepf Nope, still no tab-autocompletion. With the suggested change, I do now see the script editor load and run correctly - there are no errors, but also no tab-autocompletion.


#10

Hi @GenevieveBuckley,

TAB is not supposed to do anything. The auto-completion pulldown should show up after you entered two characters. Alternatively, you can hit Ctrl+Space (Windows/Linux) / ⌘ cmd+Space (MacOS) to open the pulldown. If the pulldown would contain just one entry, it is completed automatically.

Does that work for you?

Thanks a lot! Testing is a well-appreciated support!

Cheers,
Robert


#11

@frauzufall The IJ. issue is also fixed now. :slight_smile:


#12

Hi @haesleinhuepf,

that is so aaaaaaawwwwsome :metal:
Tested it on: (Fiji Is Just) ImageJ 2.0.0-rc-67/1.52d; Java 1.8.0_172 [64-bit]; Windows 10
and it works like a charm.

To your questions:

  1. it’s not annoying (at least not for me, since used to from Eclipse)
  2. So far, I did not figure out any interference with other workflows or shortcuts.
  3. So far, I did not detect any strange behaviour or error, just one small thing I noted… (in the “Language” tab there is IJ1 Macro appearing twice. Is this intended?)

I am aware that other scripting languages might be better suitable even for prototyping but since I am quite familiar with the IJ macro language it basically does the job. In addition it is easier to learn for not-so-computer-affine people. Therefore, this auto completion including the description as in Eclipse is super cool!
Thank you so much!


#13

Hi @biovoxxel,

thanks for the positive feedback! :slight_smile:

Its not intended, and I cannot reproduce this. Could it be that you have some jar files doubled (imagej-legacy for example?). Could you maybe try with a bare freshly downloaded Fiji? Nevertheless, we keep an eye on this.

That’s the major goal in fact. I saw quite a few non-computer-science people struggling in IJ macro courses I gave. This is for them :wink:

Thanks again!

Cheers,
Robert


#14

Hi @haesleinhuepf,

Jepp, that was the culprit. Sorry, for that false alarm :blush:


#15

The SSL exception happens when the version of Java is older than 1.8.0_101, because old Java versions do not recognize SSL certificates from Let’s Encrypt, which is what imagej.net uses. If you download a fresh Fiji, it will come with a new-enough version of Java 8 to avoid this error. It would be great if ImageJ could be taught to warn users running too-old Javas—or maybe even upgrade it, although that would be more complex.

It is Ctrl+space on macOS as well. The ⌘ cmd+Space shortcut is reserved for Spotlight.

Next usability goals for scripting:

  1. Make a Command History tool that records SciJava module executions and lets you create scripts (in any language) out of them.
  2. Expose all ImageJ macro functions to all script languages, not just IJ macro.
  3. Autocomplete them in the same way.
  4. Make the functions ImageJ2-driven as much as possible, while leaving the legacy functions all intact as well.

We need to escape the macro language’s horrible “there are no objects” limitation, while preserving the friendliness and ease-of-learning for which the macro language is renowned. We tried a few years back to shoehorn the macro language onto BeanShell, but there were four syntax limitations that prevented it from being 100% compatible. Nonetheless, it would be a tremendous step forward to get a 98%-compatible and extensible convenience library accessible from all script languages, no?

Perhaps we could file this as a “help wanted” issue somewhere.


#16

@haesleinhuepf ah, sorry I didn’t realise it was supposed to show up automatically. No, I’m definitely not seeing the auto-completion appear after entering more than two characters (eg: getD should give me getDimensions() like in your first screenshot example). Typing ⌘ cmd+Space brings up Spotlight search, rather than the pulldown.

(Nice to see this is working on other platforms!)


#17

Hi @GenevieveBuckley,

we just realised that the short cut is CTRL+SPACE, also on MacOS. Furthermore, are you sure you downloaded and installed all three JAR files and deleted older versions of them?

Cheers, Robert


#18

Hi @haesleinhuepf
Three jar files? You reference only two that I can see: script-editor-0.2.1-SNAPSHOT and batch-processor-0.1.1.jar.

I am indeed removing my original script-editor jar file, and there isn’t another batch-processor file to remove. When you say “installing the jar files”, do you mean anything different than "copy these jar files into the location: /Applications/Fiji.app/jars/"?


#19

We advanced a bit :wink: With these three it should work. You understood installation correctly. Just put the third JAR in the same folder an remove any other image-legacy.jar


#20

This is really cool! I can’t be the only one who goes to the macro language reference many times a day.

Just tried with a fresh install of Fiji and the latest 3 JARs. Works great on Windows 7 and 10. I like the descriptions of the commands and automatically filling in the variables where required is helpful.

Whether the popup appears seems a little flaky when you start backspacing commands. For example, if you type getD you get the popup, if you backspace to ge, then start typing again, it does not appear again (for me). Is this expected behaviour? If I wanted to get the popup again, I needed to delete the whole word and start typing again.

Also, don’t know if someone mentioned this before but it would be nice to have the eg. run(“Split Channels”) options from the menus available. Don’t know how difficult or not this is to include though.