Shift-clicking on menu item to open script editor

script-editor
menu
scripting
Tags: #<Tag:0x00007fd540173758> #<Tag:0x00007fd5401735f0> #<Tag:0x00007fd5401734b0>

#1

Up to a recent update of Fiji, there was a (poorly documented but) very useful function that allowed opening a script for editing by Shift-clicking its menu entry.
Since the latest round of Fiji updates, this still opens the script editor, but the text field is empty (tested on Windows 7 and Mac OS 10.11.5).

I suspect that the breaking change would be somewhere in scijava-ui-swing, in script-editor or in imagej-legacy.

@ctrueden any ideas where this might be happening?


Along these lines, I noticed that in the Command Finder, clicking on the Source button won’t work for scripts but instead produces error messages like this:

Unable to display source for this plugin: C:\UTILIT~1\Fiji.app\plugins\script:Examples/downsample_/js

#2

The problem is caused by this commit: scijava/scijava-common@ff73f88a.

And relatedly, the shift key logic for scripts lives in imagej-legacy.

The problem is that script.getPath() returns a relative path—e.g., the Plugins :arrow_forward: Examples :arrow_forward: Fiji Cube returns the value Examples/Fiji_Cube.ijm, which is correct relative to one of the script directory prefixes. The issue is that there is more than one script directory prefix. From the Script Interpreter:

>>> script.getScriptDirectories()
[/Applications/Fiji.app/scripts, /Applications/Fiji.app/plugins/Scripts, /Applications/Fiji.app/plugins]

(As an aside: Why do we have both plugins/Scripts and plugins anyway? It results in scripts being scattered across different subtrees.)

Anyway, the ScriptFinder now constructs ScriptInfo objects with only a relative path, excluding the associated script directory prefix. This is OK, because the ScriptInfo now has the whole script in memory, read from a URL into the script field, which can then be fed back any time via the getReader() method.

I fixed it by calling getReader() first to access the script contents, before falling back to getPath(). This also has the handy side effect of making scripts stored inside JAR files shift-clickable too! :grin:

One remaining bug is that the language is still not set correctly, but I am too tired to fix that tonight.

If you have time, please test and let me know how it goes. There are other critical pending bug-fixes in imagej-legacy right now too, so I will be cutting a new release and uploading some time tomorrow, unless you find any showstopper problems.


#3

@ctrueden sorry for getting back to this only now.

The script is now opened in the script editor, but because it was dealing with relative paths only, it forgets about the original path, so when trying to save changes, you get a new Save As dialog instead of just writing back to the original file inside ./Fiji.app/ (which used to be quite handy when editing scripts that are called by other scripts via their menu command).

Any chance that we can fully restore the old behavior while keeping the possibility to open scripts from JARs? Of course, scripts inside JARs cannot be saved that way, but for local script files it still would be helpful.

Maybe we can make script.getPath() always return the path relative to ./Fiji.app/ and include the information about the subfolder?


#4

Of course. Here is my first attempt:

I did not have time to test whatsoever. Please build scijava-common with mvn clean install and then the same for imagej-legacy. And copy those two artifacts to your Fiji installation to test. It would be ideal to test for both the script-inside-a-JAR and script-not-in-a-JAR cases, and make sure both behave completely properly.

Once I have confirmation of that, I will merge these, cut releases, and upload.

All I ask is in return: someday, and that day may never come, I’ll call upon you to do a service for me. And that service will involve reading a complete draft of the ImageJ2 paper and offering your suggestions. :wink:


#5

Thanks @ctrueden for the quick reply!

In my tests, the following works now:

  • Shift-clicking on a menu command pointing to a local script opens the file in script editor
  • Clicking on a menu command pointing to a local script runs the script
  • Clicking on a menu command pointing to a script in a jar runs the script

But the following throws an exception:

  • Shift-clicking on a menu command pointing to a script in a jar gives:

    (Fiji Is Just) ImageJ 2.0.0-rc-54/1.51g; Java 1.8.0_102 [64-bit]; Windows 7 6.1; 441MB of 96000MB (<1%)
     
    java.lang.IllegalArgumentException: URI is not hierarchical
        at java.io.File.<init>(File.java:418)
        at net.imagej.legacy.LegacyService.getScriptFile(LegacyService.java:709)
        at net.imagej.legacy.LegacyService.openScriptInTextEditor(LegacyService.java:666)
        at net.imagej.legacy.LegacyService.runLegacyCompatibleCommand(LegacyService.java:295)
        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)
    

I tried to catch the IllegalArgumentException to see if the script can be opened anyways via its ScriptInfo, but then the script editor content is:

[Cannot load script: test/My_Script.py]

I conclude this is because the reader is null here:

and subsequently the StringBuilder has zero length:

As I still didn’t understand all the logic behind the ScriptInfo class and won’t have time to dig into this until Tuesday next week, I’ll have to give up for now.


NB Something I noticed earlier already but never judged it important enough to file an issue: on Windows, shift-clicking a menu entry only works when you start holding the Shift key before clicking on the top-level menu and keep it pressed until clicking on the command. It won’t work if you just start holding it immediately before clicking the command, when the menu or submenu is already displayed.


I’ll be delighted to do that anytime you ask. :slight_smile:


#6

Thanks for testing. I force-pushed the fix:

And I also fixed an issue in script-editor:

Now, e.g., if you have a script in jars/scripts.jar under scripts/Image/Rock_My_World.ijm and then shift-click it in the menu, and then subsequently save it, it will save to $FIJI_HOME/scripts/Image/Rock_My_World.ijm even if the scripts/Image directory did not exist beforehand. And then when you restart Fiji, that version will take precedence over the JAR file henceforth. :grin:

That is indeed annoying. Could you please file an issue in imagej/imagej-legacy? I briefly looked at the code, but it is tricky—will take a debugging session to get to the bottom of it due to how the legacy layer intercepts certain events in IJ1.


#7

I merged the topic branches in scijava-common and script-editor. The imagej-legacy one is still not merged, because it requires that SciJava Common be released first. Will do later.


#8

@imagejan I merged the imagej-legacy branch.

It would still be good if you could file an issue for the Windows shift key bug above.


#9

I finally filed the issue so that we don’t forget. Sorry for the delay.