Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add things to default JavaScriptLanguageSupport #5

Open
iberck opened this issue Nov 12, 2013 · 10 comments
Open

Add things to default JavaScriptLanguageSupport #5

iberck opened this issue Nov 12, 2013 · 10 comments
Labels

Comments

@iberck
Copy link

iberck commented Nov 12, 2013

Hello first of all thanks for your effort making this magnificent library.

I'm using the latest version of library (rsyntaxtextarea, autocomplete, languagesupport) and I have been researching all weekend adding stuff to support javascript autocomplete but my snippets not work.

I'm using the autocomplete javascript support language and I want to add code templates and support of autocomplete of my own classes to the default javascript default autocomplete support.

My base code is:

    private RSyntaxTextArea createTextAreaEditor() {
        textAreaEditor = new RSyntaxTextArea();
        textAreaEditor.setCaretPosition(0);
        textAreaEditor.requestFocusInWindow();
        textAreaEditor.setMarkOccurrences(true);
        textAreaEditor.setTabsEmulated(true);
        textAreaEditor.setTabSize(4);
        ToolTipManager.sharedInstance().registerComponent(textAreaEditor);

        textAreaEditor.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT);
        textAreaEditor.setCodeFoldingEnabled(true);
        textAreaEditor.setAntiAliasingEnabled(true);

        return textAreaEditor;
    }

    private void createLanguageSupport() {
        LanguageSupportFactory lsf = LanguageSupportFactory.get();
        lsf.register(textAreaEditor);
        LanguageSupport support = lsf.getSupportFor(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT);
        JavaScriptLanguageSupport languageSupport = (JavaScriptLanguageSupport) support;
        try {
            languageSupport.getJarManager().addCurrentJreClassFileSource();
        } catch (IOException ex) {
            Logger.getLogger(ScriptEditorJDialog.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

with the the above code the javascript autocomplete default support works fine, when I press "ctrl+." appears a autocomplete with javascript basic functions however I don't know how can add something to autocomplete javascript default support.

My first doubt (add codetemplates to javascript elements):
How can I archive press "Ctrl +.​" and add the new item "log" with the default autocomplete javascript elements?

My second doubt (autocomplete my own classes):
I use in my scripts the java class: "com.example.MyClass" wich is in the "client.jar" file,
My problem is when I define a var of type "MyClass", the autocomplete of membes/methods of var MyClass does not work.
Y define the vars like:

    var n = new Packages.com.example.MyClass();
    n. (autocomplete does not work)
    var r = new MyClass();
    r. (autocomplete does not work)

How can I archive this?
I tried with several examples I've found in the forums but I can not make it work, for example I have tried to add class file source to the jarManager but does not do what I want:

    LanguageSupportFactory lsf = LanguageSupportFactory.get();
    lsf.register(textAreaEditor);
    LanguageSupport support = lsf.getSupportFor(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT);
    JavaScriptLanguageSupport languageSupport = (JavaScriptLanguageSupport) support;
    JarManager jarManager = languageSupport.getJarManager();
    try {
        jarManager.addClassFileSource(new JarLibraryInfo("d:/projects/client.jar"));
    } catch (IOException ex) {
        Logger.getLogger(ScriptEditorJDialog.class.getName()).log(Level.SEVERE, null, ex);
    }       

I'm using netbeans rcp framework.
Thank you very much for your time and help.

@iberck
Copy link
Author

iberck commented Dec 3, 2013

anyone can help me ?

@stevenupton
Copy link
Collaborator

Hi iberck

To enabled this you need to enable the Rhino Engine support for the SourceCompletionProvider. To do this you need to override the JavaScriptLanguageSupport class and register this instead of the regular JavaScript support.

Firstly you will need to write a class like this:

 import org.fife.rsta.ac.LanguageSupport;
 import org.fife.rsta.ac.js.JavaScriptCompletionProvider;
 import org.fife.rsta.ac.js.JavaScriptLanguageSupport;
 import org.fife.rsta.ac.js.SourceCompletionProvider;
 import org.fife.rsta.ac.js.ast.type.ecma.v5.TypeDeclarationsECMAv5;
 import org.fife.rsta.ac.js.engine.RhinoJavaScriptEngine;
 import org.fife.ui.rsyntaxtextarea.RSyntaxTextArea;
 import org.fife.ui.rsyntaxtextarea.modes.JavaScriptTokenMaker;

public class RhinoJavaScriptLanguageSupport extends JavaScriptLanguageSupport
{
    private static final String ENGINE = RhinoJavaScriptEngine.RHINO_ENGINE;

public RhinoJavaScriptLanguageSupport()
{
    JavaScriptTokenMaker.setJavaScriptVersion("1.7");
    setECMAVersion(TypeDeclarationsECMAv5.class.getName(), getJarManager());
}

@Override
protected JavaScriptCompletionProvider createJavaScriptCompletionProvider()
{
    return new JavaScriptCompletionProvider(new MySourceCompletionProvider(), getJarManager(), this);
}
public void install(RSyntaxTextArea textArea)
{
    //remove javascript support and replace with Rhino support
    LanguageSupport support = (LanguageSupport)textArea.getClientProperty("org.fife.rsta.ac.LanguageSupport");
    if (support!=null) {
        support.uninstall(textArea);
    }
    super.install(textArea);
}
private class MySourceCompletionProvider extends SourceCompletionProvider
{
   public MySourceCompletionProvider()
    {
        super(ENGINE, false);
    }
}
}

You will need to register the class with the RSyntaxTextArea like this:

private RSyntaxTextArea createTextAreaEditor() {
    textAreaEditor = new RSyntaxTextArea();
    textAreaEditor.setCaretPosition(0);
    textAreaEditor.requestFocusInWindow();
    textAreaEditor.setMarkOccurrences(true);
    textAreaEditor.setTabsEmulated(true);
    textAreaEditor.setTabSize(4);
    ToolTipManager.sharedInstance().registerComponent(textAreaEditor);

    textAreaEditor.setSyntaxEditingStyle(SyntaxConstants.SYNTAX_STYLE_JAVASCRIPT);
    textAreaEditor.setCodeFoldingEnabled(true);
    textAreaEditor.setAntiAliasingEnabled(true);

    configureLanguageSupport(textAreaEditor);
    return textAreaEditor;
}

private void configureLanguageSupport(RSyntaxTextArea textArea) throws IOException
{

    RhinoJavaScriptLanguageSupport support1 = new RhinoJavaScriptLanguageSupport();
    JarManager jarManager = support1.getJarManager();
    jarManager.addCurrentJreClassFileSource();
    //add additional libraries and classes
    jarManager.addClassFileSource(new JarLibraryInfo("d:/projects/client.jar"));
    support1.install(textArea);
}

Note that if you have the source file in the library archive also, you will also see the Javadoc comments for the methods and fields.

Also you will be able to import package using the syntax:

package(java.io);
var myFile = new File();
.....

The auto complete for Java classes should really be implemented in the JSR223JavaScriptEngine, but has not been moved yet. Also it needs to be easier to switch modes between the engines instead of overriding an entire class.

Anyway. I hope this helps.

Steve

@iberck
Copy link
Author

iberck commented Dec 3, 2013

thanks for your answer Mr. Steve Upton, I will try with the above code.
Regards.

@iberck
Copy link
Author

iberck commented Dec 7, 2013

Steve:

I have tried with your example and it works, thank you very much !

Can you help me with another question?

How can I add custom completions to JavaScriptCompletionProvider, for example add a code template for insert a predefined constant when press ctrl + space ?

I have tried adding a basic completion in constructor of MySourceCompletionProvider but it does not work:

private class MySourceCompletionProvider extends SourceCompletionProvider {

        public MySourceCompletionProvider() {
            super(ENGINE, false);
            addCompletion(new BasicCompletion(this, "abstract", "this is the description", "this is the summary"));
        }
}

Thanks in advance.

@stevenupton
Copy link
Collaborator

Hi iberck,

The object you really need is the ShotHandCompletionCache inside the Source completion provider. But you cannot access this because it is not protected and does not have a getter. A bit of an oversight.

The whole API needs a bit of work.

Anyway, you can get round it by modifying your overridden SourceCompletion class as before and intercepting the getAlreadyEnteredText method... e.g

private class MySourceCompletionProvider extends SourceCompletionProvider {
    private ArrayList<Completion> myCompletions = new ArrayList<Completion>();

    public MySourceCompletionProvider()
    {
        super(ENGINE, false);
        createMyCompletions();
    }

    private void createMyCompletions()
    {
        //add my completions here
        myCompletions.add( new MyBasicCompletion(this, "abstract", "this is the description", "this is the summary"));
    }


    public String getAlreadyEnteredText(JTextComponent comp) {

        String text = super.getAlreadyEnteredText(comp);
        if(text != null && text.length() > 0) //only add the completions if text is entered, remove this check to always add them
            completions.addAll(myCompletions);
        return text;
    }

    private  class MyBasicCompletion extends BasicCompletion implements JSCompletionUI
    {

        public MyBasicCompletion(CompletionProvider provider, String replacementText, String shortDesc, String summary)
        {
            super(provider, replacementText, shortDesc, summary);
        }

        @Override
        public int getRelevance()
        {
            //keep me to the bottom of the completions
            return TEMPLATE_RELEVANCE;
        }


    }
}

This is not pretty, but there is not other way to add the completions. Looks like a big hole in the API.

Kind regards

Steve

@iberck
Copy link
Author

iberck commented Dec 9, 2013

Hi Steve:

Thank you for your answer and your time, I will try with it.

@iberck
Copy link
Author

iberck commented Dec 10, 2013

Thanks again Steve, the example works fine for my purposes, are there any way to add custom highlight to default javascript highlight, for example highlight the "importPackage" sentence?

I have tried modifing JavaScriptTokenMaker.flex, are there any best way ?

Kind regards.

@stevenupton
Copy link
Collaborator

The only way I have changed this is to modify the flex and recompile it.

The importPackage is Rhino specific, so maybe there needs to be a RhinoJavaScript.flax file?

I originally added the JavaScript syntax/autocomplete as I needed it for a project at work. It is loosely based on the Java completions. It is not completely finished and some bits needs reworking as inner functions do not work that well. I have written all the JavaScript API as Java classes and pass them, but I would like to replace this with pure JavaScript files once I (or someone else) have fixed the inner functions and other areas I have missed.

On the whole, I would expect it to support most autocomplete/syntax.

Steve

@iberck
Copy link
Author

iberck commented Dec 20, 2013

Thank you steve, it works !!!

@rashmijl
Copy link

Hi ,

I want to know how to apply custom javascript library to language support?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants