anon
anon

Reputation:

How can I get the selected code in Eclipse?

For my plugin I'm trying to access the selected code in a CompilationUnitEditor. Therefore I added a contribution to the context menu and use following code:

public class ContextMenuHandler implements IEditorActionDelegate {

    private IEditorPart editorPart;

    @Override
    public void setActiveEditor(IAction action, IEditorPart editorPart) {
        this.editorPart = editorPart;
    }

    @Override
    public void run(IAction action) {
        JavaUI.getEditorInputJavaElement(editorPart.getEditorInput());
    }

    @Override
    public void selectionChanged(IAction action, ISelection selection) {
        if (selection instanceof TextSelection) {
            TextSelection text = (TextSelection) selection;
            System.out.println("Text: " + text.getText());
        } else {
            System.out.println(selection);
        }
    }

}

Now the problem is that the method selectionChanged(...) is only called when i really select something so that I could copy/paste it. But I want to access the Code elements that are highlighted like this (here I would like to get the "IEditorPart")

enter image description here

Unfortunately, I have no idea what I should look for.

Upvotes: 6

Views: 2432

Answers (3)

anon
anon

Reputation:

Using the inputs from the other answers, I ended up with the following solution:

@Override
public void setActiveEditor(IAction action, IEditorPart editorPart) {
    ((CompilationUnitEditor) editorPart).getViewer().addTextListener(new ITextListener() {

        @Override
        public void textChanged(TextEvent event) {
            selectedText = event.getText();
        }
    });

}

Upvotes: 1

Alex
Alex

Reputation: 25613

Wouldn't it be easier to detect the caret current position. Having the position let you easily detect if the caret is on a word (define word as you like, for example space-separated, java identifier, or with a regular expression).

I'm not able to run eclipse here, but I would use the CaretListener class in order to detect caret movements and thus extracting the word under it. The CaretEvent given as parameter to the caretMoved method will contain the offset.

The CaretListener can be attached to the Adapter of your StyledText component, that you can get from your EditorPart (don't have any more info for the moment, as I don't have eclipse running here).

Hope it helps.

Edit: Some code.

final StyledText text = (StyledText)editorPart.getAdapter(Control.class);
text.addCaretListener(new CaretListener() {
        public void caretMoved(CaretEvent event) {
            int offset = event.caretOffset;
            String word = findWord(offset, text);
            if (word.length() > 0) {
                System.out.println("Word under caret: " + word);
            }
        }
});

private String findWord(int offset, StyledText text) {
    int lineIndex = text.getLineAtOffset(offset);
    int offsetInLine = offset - text.getOffsetAtLine(lineIndex);
    String line = text.getLine(lineIndex);
    StringBuilder word = new StringBuilder();
    if (offsetInLine > 0 && offsetInLine < line.length()) {
        for (int i = offsetInLine; i >= 0; --i) {
            if (!Character.isSpaceChar(line.charAt(i))) {
                word.append(line.charAt(i));
            } else {
                break;
            }
        }
        word = word.reverse();
    }
    if (offsetInLine < line.length()) {
        for (int i = offsetInLine; i < line.length(); ++i) {
            if (i == offsetInLine)
                continue; // duplicate
            if (!Character.isSpaceChar(line.charAt(i))) {
                word.append(line.charAt(i));
            } else {
                break;
            }
        }
    }
    return word.toString();
}

This is simple implementation to get the word under the cursor based on space character surrounding it. A more robust implementation should be used in order to detect valid Java identifiers etc. For example using Character.isJavaIdentifierStart and Character.isJavaIdentifierPart or using a library for this.

Upvotes: 3

Andrew Eisenberg
Andrew Eisenberg

Reputation: 28737

You should do this:

        ((CompilationUnitEditor) editorPart).getViewer().getSelectedRange();

The ISourceViewer class has quite a few useful and interesting methods regarding source locations and the editor. You may also want to look at JavaSourceViewer.


EDIT

It looks like I didn't quite answer your question. The problem is that selectionChanged events are only called when the length of the selection is > 0. I don't know why this is the case, but that is the way action delegates have always worked.

If you want to be notified whenever the caret changes, you should register a selection changed listener with the viewer for the editor. Do something like this:

((CompilationUnitEditor) editorPart).getViewer()
  .addSelectionChangedListener(mySelectionListener);

mySelectionListener is of type org.eclipse.jface.viewers.ISelectionChangedListener. Registering in this way, should give you all the events you are looking for. Just be careful to unregister when the editor closes.

Upvotes: 7

Related Questions