diff --git a/tutorials/editor/editor_basics.md b/tutorials/editor/editor_basics.md index 97cd610a4..60c5e5b34 100644 --- a/tutorials/editor/editor_basics.md +++ b/tutorials/editor/editor_basics.md @@ -43,11 +43,13 @@ it will be available from the context menu when the focus is located in the edit To determine conditions by which the action will be visible and available for being executed we need to override it's *public void update(final AnActionEvent e)* method. - public class EditorIllustration extends AnAction { - @Override - public void update(final AnActionEvent e) { - } +```java +public class EditorIllustration extends AnAction { + @Override + public void update(final AnActionEvent e) { } +} +``` If we want to work with a selected part of the text, it's reasonable to make the action available only when the following requirements are met: @@ -61,16 +63,18 @@ Further steps will show how to check these conditions through obtaining instance A reference to an instance of the Editor can be obtained by calling ```CommonDataKeys.EDITOR```, obtaining a project reference is performed the same way ```CommonDataKeys.PROJECT```. - public class EditorIllustration extends AnAction { - @Override - public void update(final AnActionEvent e) { - //Get required data keys - final Project project = e.getData(CommonDataKeys.PROJECT); - final Editor editor = e.getData(CommonDataKeys.EDITOR); - //Set visibility only in case of existing project and editor - e.getPresentation().setVisible((project != null && editor != null)); - } +```java +public class EditorIllustration extends AnAction { + @Override + public void update(final AnActionEvent e) { + //Get required data keys + final Project project = e.getData(CommonDataKeys.PROJECT); + final Editor editor = e.getData(CommonDataKeys.EDITOR); + //Set visibility only in case of existing project and editor + e.getPresentation().setVisible((project != null && editor != null)); } +} +``` ------------------ @@ -90,17 +94,19 @@ After making sure we have a project open and an instance of the Editor we need t [SelectionModel] () got from the Editor allows to do it by calling it's ```hasSelection()``` method. Here's how our ```update(final AnActionEvent e)``` method should look like at the end: - public class EditorIllustration extends AnAction { - @Override - public void update(final AnActionEvent e) { - //Get required data keys - final Project project = e.getData(CommonDataKeys.PROJECT); - final Editor editor = e.getData(CommonDataKeys.EDITOR); - //Set visibility only in case of existing project and editor and if some text in the editor is selected - e.getPresentation().setVisible((project != null && editor != null - && editor.getSelectionModel().hasSelection())); - } +```java +public class EditorIllustration extends AnAction { + @Override + public void update(final AnActionEvent e) { + //Get required data keys + final Project project = e.getData(CommonDataKeys.PROJECT); + final Editor editor = e.getData(CommonDataKeys.EDITOR); + //Set visibility only in case of existing project and editor and if some text in the editor is selected + e.getPresentation().setVisible((project != null && editor != null + && editor.getSelectionModel().hasSelection())); } +} +``` ------------ @@ -123,15 +129,17 @@ package and include: The action is visible and available now. In order to make it do something we need to override it's ```public void actionPerformed(final AnActionEvent anActionEvent)``` method. - public class EditorIllustration extends AnAction { - @Override - public void update(final AnActionEvent e) { - //code here - } - @Override - public void actionPerformed(final AnActionEvent anActionEvent) { - } +```java +public class EditorIllustration extends AnAction { + @Override + public void update(final AnActionEvent e) { + //code here } + @Override + public void actionPerformed(final AnActionEvent anActionEvent) { + } +} +``` To modify the text an instance of the [Document] (https://github.com/JetBrains/intellij-community/blob/master/platform/core-api/src/com/intellij/openapi/editor/Document.java) @@ -139,17 +147,19 @@ needs to be accessed. Document represents the contents of a text file loaded int The instance of a Document will be use later when a text replacement is performed. We also need to figure out where the selected part of the text is located. - @Override - public void actionPerformed(final AnActionEvent anActionEvent) { - //Get all the required data from data keys - final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); - final Project project = anActionEvent.getRequiredData(CommonDataKeys.PROJECT); - //Access document, caret, and selection - final Document document = editor.getDocument(); - final SelectionModel selectionModel = editor.getSelectionModel(); - final int start = selectionModel.getSelectionStart(); - final int end = selectionModel.getSelectionEnd(); - } +```java +@Override +public void actionPerformed(final AnActionEvent anActionEvent) { + //Get all the required data from data keys + final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); + final Project project = anActionEvent.getRequiredData(CommonDataKeys.PROJECT); + //Access document, caret, and selection + final Document document = editor.getDocument(); + final SelectionModel selectionModel = editor.getSelectionModel(); + final int start = selectionModel.getSelectionStart(); + final int end = selectionModel.getSelectionEnd(); +} +``` ##Modifying text Generally replacement can be done by calling @@ -160,28 +170,30 @@ See [Threading Issues](https://confluence.jetbrains.com/display/IDEADEV/IntelliJ+IDEA+Architectural+Overview#IntelliJIDEAArchitecturalOverview-Threading) section to know more about synchronization issues and changes safety in IntelliJ. - @Override - public void actionPerformed(final AnActionEvent anActionEvent) { - //Get all the required data from data keys - final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); - final Project project = anActionEvent.getRequiredData(CommonDataKeys.PROJECT); - //Access document, caret, and selection - final Document document = editor.getDocument(); - final SelectionModel selectionModel = editor.getSelectionModel(); +```java +@Override +public void actionPerformed(final AnActionEvent anActionEvent) { + //Get all the required data from data keys + final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); + final Project project = anActionEvent.getRequiredData(CommonDataKeys.PROJECT); + //Access document, caret, and selection + final Document document = editor.getDocument(); + final SelectionModel selectionModel = editor.getSelectionModel(); - final int start = selectionModel.getSelectionStart(); - final int end = selectionModel.getSelectionEnd(); - //New instance of Runnable to make a replacement - Runnable runnable = new Runnable() { - @Override - public void run() { - document.replaceString(start, end, "Replacement"); - } - }; - //Making the replacement - WriteCommandAction.runWriteCommandAction(project, runnable); - selectionModel.removeSelection(); - } + final int start = selectionModel.getSelectionStart(); + final int end = selectionModel.getSelectionEnd(); + //New instance of Runnable to make a replacement + Runnable runnable = new Runnable() { + @Override + public void run() { + document.replaceString(start, end, "Replacement"); + } + }; + //Making the replacement + WriteCommandAction.runWriteCommandAction(project, runnable); + selectionModel.removeSelection(); +} +``` ----------- @@ -206,37 +218,39 @@ Access to the Editor is performed through an action. ##Accessing caret positions To get an access to caret positions an instance of CaretModel should be obtained. - public class EditorAreaIllustration extends AnAction { - @Override - public void actionPerformed(AnActionEvent anActionEvent) { - final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); - CaretModel caretModel = editor.getCaretModel(); - } - - @Override - public void update(AnActionEvent e) { - //... - } +```java +public class EditorAreaIllustration extends AnAction { + @Override + public void actionPerformed(AnActionEvent anActionEvent) { + final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); + CaretModel caretModel = editor.getCaretModel(); } + @Override + public void update(AnActionEvent e) { + //... + } +} +``` ##Logical position [LogicalPosition.java] (https://github.com/JetBrains/intellij-community/blob/master/platform/editor-ui-api/src/com/intellij/openapi/editor/LogicalPosition.java) represents a line and a column of the current logical position of the caret. Logical positions ignore folding - for example, if the top 10 lines of the document are folded, the 10th line in the document will have the line number 10 in its logical position. - public class EditorAreaIllustration extends AnAction { - @Override - public void actionPerformed(AnActionEvent anActionEvent) { - final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); - CaretModel caretModel = editor.getCaretModel(); - LogicalPosition logicalPosition = caretModel.getLogicalPosition(); - } - - @Override - public void update(AnActionEvent e) { - //... - } - } +```java +public class EditorAreaIllustration extends AnAction { + @Override + public void actionPerformed(AnActionEvent anActionEvent) { + final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); + CaretModel caretModel = editor.getCaretModel(); + LogicalPosition logicalPosition = caretModel.getLogicalPosition(); + } + @Override + public void update(AnActionEvent e) { + //... + } +} +``` Logical position may store additional parameters that define its mapping to [VisualPosition.java] (https://github.com/JetBrains/intellij-community/blob/master/platform/editor-ui-api/src/com/intellij/openapi/editor/VisualPosition.java). @@ -250,62 +264,65 @@ represent a visual position and may very from the corresponding logical position Visual positions take folding into account - for example, if the top 10 lines of the document are folded, the 10th line in the document will have the line number 1 in its visual position. - public class EditorAreaIllustration extends AnAction { - @Override - public void actionPerformed(AnActionEvent anActionEvent) { - final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); - CaretModel caretModel = editor.getCaretModel(); - LogicalPosition logicalPosition = caretModel.getLogicalPosition(); - VisualPosition visualPosition = caretModel.getVisualPosition(); - } - - @Override - public void update(AnActionEvent e) { - //... - } - } +```java +public class EditorAreaIllustration extends AnAction { + @Override + public void actionPerformed(AnActionEvent anActionEvent) { + final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); + CaretModel caretModel = editor.getCaretModel(); + LogicalPosition logicalPosition = caretModel.getLogicalPosition(); + VisualPosition visualPosition = caretModel.getVisualPosition(); + } + @Override + public void update(AnActionEvent e) { + //... + } +} +``` ##Offset An absolute offset for a given caret position is accessible through CaretModel as well - public class EditorAreaIllustration extends AnAction { - @Override - public void actionPerformed(AnActionEvent anActionEvent) { - final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); - CaretModel caretModel = editor.getCaretModel(); - LogicalPosition logicalPosition = caretModel.getLogicalPosition(); - VisualPosition visualPosition = caretModel.getVisualPosition(); - int offset = caretModel.getOffset(); - } - - @Override - public void update(AnActionEvent e) { - //... - } +```java +public class EditorAreaIllustration extends AnAction { + @Override + public void actionPerformed(AnActionEvent anActionEvent) { + final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); + CaretModel caretModel = editor.getCaretModel(); + LogicalPosition logicalPosition = caretModel.getLogicalPosition(); + VisualPosition visualPosition = caretModel.getVisualPosition(); + int offset = caretModel.getOffset(); } + @Override + public void update(AnActionEvent e) { + //... + } +} +``` ##Displaying position values To display the actual values of logical anf visual positions we add an ```Messages.showInfoMessage()``` call that will show them in form of notification after the action is performed. - public class EditorAreaIllustration extends AnAction { - @Override - public void actionPerformed(AnActionEvent anActionEvent) { - final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); - CaretModel caretModel = editor.getCaretModel(); - LogicalPosition logicalPosition = caretModel.getLogicalPosition(); - VisualPosition visualPosition = caretModel.getVisualPosition(); - int offset = caretModel.getOffset(); - Messages.showInfoMessage(logicalPosition.toString() + "\n" + +```java +public class EditorAreaIllustration extends AnAction { + @Override + public void actionPerformed(AnActionEvent anActionEvent) { + final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); + CaretModel caretModel = editor.getCaretModel(); + LogicalPosition logicalPosition = caretModel.getLogicalPosition(); + VisualPosition visualPosition = caretModel.getVisualPosition(); + int offset = caretModel.getOffset(); + Messages.showInfoMessage(logicalPosition.toString() + "\n" + visualPosition.toString() + "\n" + "Offset: " + offset, "Caret Parameters Inside The Editor"); - } - - @Override - public void update(AnActionEvent e) { - //... - } - } + } + @Override + public void update(AnActionEvent e) { + //... + } +} +``` Check out, compile, and run the [Editor Basics Plugin] (https://github.com/JetBrains/intellij-sdk/tree/master/code_samples/editor_basics), @@ -332,31 +349,35 @@ Series of steps below shows how to change standard behaviour of the editor and m First we need to implement an instance of [TypedActionHandler](): - public class MyTypedHandler implements TypedActionHandler { - @Override - public void execute(@NotNull Editor editor, char c, @NotNull DataContext dataContext) { - } +```java +public class MyTypedHandler implements TypedActionHandler { + @Override + public void execute(@NotNull Editor editor, char c, @NotNull DataContext dataContext) { } +} +``` ###Implementing logic for handling keystrokes ```public void execute(@NotNull Editor editor, char c, @NotNull DataContext dataContext);``` method should contain the main logical part for handling keystrokes. It will be called every time a key is pressed. In the following example our typed handler is meant insert a string at the zero offset in the editor after a keystroke occurs: - public class MyTypedHandler implements TypedActionHandler { - @Override - public void execute(@NotNull Editor editor, char c, @NotNull DataContext dataContext) { - final Document document = editor.getDocument(); - Project project = editor.getProject(); - Runnable runnable = new Runnable() { - @Override - public void run() { - document.insertString(0, "Typed\n"); - } - }; - WriteCommandAction.runWriteCommandAction(project, runnable); - } +```java +public class MyTypedHandler implements TypedActionHandler { + @Override + public void execute(@NotNull Editor editor, char c, @NotNull DataContext dataContext) { + final Document document = editor.getDocument(); + Project project = editor.getProject(); + Runnable runnable = new Runnable() { + @Override + public void run() { + document.insertString(0, "Typed\n"); + } + }; + WriteCommandAction.runWriteCommandAction(project, runnable); } +} +``` ###Setting up *TypedActionHandler* @@ -365,13 +386,15 @@ To enable a custom implementation of *TypedActionHandler* in the plugin we need [TypedAction]() class. By doing it we replace the typing handler with the specified handler. - public class EditorIllustration extends AnAction { - static { - final EditorActionManager actionManager = EditorActionManager.getInstance(); - final TypedAction typedAction = actionManager.getTypedAction(); - typedAction.setupHandler(new MyTypedHandler()); - } +```java +public class EditorIllustration extends AnAction { + static { + final EditorActionManager actionManager = EditorActionManager.getInstance(); + final TypedAction typedAction = actionManager.getTypedAction(); + typedAction.setupHandler(new MyTypedHandler()); } +} +``` After compiling and running the code snippet above typing in the editor will be handled with inserting an extra string at the 0 position. @@ -385,40 +408,46 @@ In this example we will use *EditorActionHandler* to insert one extra caret abov ###Prerequirements Create an action: - public class EditorHandlerIllustration extends AnAction { - @Override - public void actionPerformed(@NotNull AnActionEvent anActionEvent) { - } - @Override - public void update(@NotNull final AnActionEvent anActionEvent) { - } +```java +public class EditorHandlerIllustration extends AnAction { + @Override + public void actionPerformed(@NotNull AnActionEvent anActionEvent) { } + @Override + public void update(@NotNull final AnActionEvent anActionEvent) { + } +} +``` Register action in [plugin.xml](): - - - - +```xml + + + + +``` ###Setting visibility Our action should be visible only in case if the following conditions are met: there's a project open, there's an editor available, and there's at least one caret active in the editor: - public class EditorHandlerIllustration extends AnAction { - @Override - public void actionPerformed(@NotNull AnActionEvent anActionEvent) { - } - @Override - public void update(@NotNull final AnActionEvent anActionEvent) { - final Project project = anActionEvent.getData(CommonDataKeys.PROJECT); - final Editor editor = anActionEvent.getData(CommonDataKeys.EDITOR); - anActionEvent.getPresentation().setVisible((project != null && editor != null && !editor.getCaretModel().getAllCarets().isEmpty())); - } +```java +public class EditorHandlerIllustration extends AnAction { + @Override + public void actionPerformed(@NotNull AnActionEvent anActionEvent) { } + @Override + public void update(@NotNull final AnActionEvent anActionEvent) { + final Project project = anActionEvent.getData(CommonDataKeys.PROJECT); + final Editor editor = anActionEvent.getData(CommonDataKeys.EDITOR); + anActionEvent.getPresentation().setVisible((project != null && editor != null && !editor.getCaretModel().getAllCarets().isEmpty())); + } +} +``` ###Obtaining *EditorActionHandler* @@ -427,37 +456,40 @@ an instance of [EditorActionHandler]() for the action we'd like to work with. Ih this case it will be an instance of [CloneCaretActionHandler](). - public class EditorHandlerIllustration extends AnAction { - @Override - public void actionPerformed(@NotNull AnActionEvent anActionEvent) { - final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); - EditorActionManager actionManager = EditorActionManager.getInstance(); - EditorActionHandler actionHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW); - } - - @Override - public void update(@NotNull final AnActionEvent anActionEvent) { - //... - } +```java +public class EditorHandlerIllustration extends AnAction { + @Override + public void actionPerformed(@NotNull AnActionEvent anActionEvent) { + final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); + EditorActionManager actionManager = EditorActionManager.getInstance(); + EditorActionHandler actionHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW); } + @Override + public void update(@NotNull final AnActionEvent anActionEvent) { + //... + } +} +``` ###Making *EditorActionHandler* execute actions To execute an action we need to call the ```public final void execute(@NotNull Editor editor, @Nullable final Caret contextCaret, final DataContext dataContext);``` method of a corresponding *EditorActionHandler* - public class EditorHandlerIllustration extends AnAction { - @Override - public void actionPerformed(@NotNull AnActionEvent anActionEvent) { - final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); - EditorActionManager actionManager = EditorActionManager.getInstance(); - EditorActionHandler actionHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW); - actionHandler.execute(editor, editor.getCaretModel().getCurrentCaret(), anActionEvent.getDataContext()); - } - @Override - public void update(@NotNull final AnActionEvent anActionEvent) { - // - } +```java +public class EditorHandlerIllustration extends AnAction { + @Override + public void actionPerformed(@NotNull AnActionEvent anActionEvent) { + final Editor editor = anActionEvent.getRequiredData(CommonDataKeys.EDITOR); + EditorActionManager actionManager = EditorActionManager.getInstance(); + EditorActionHandler actionHandler = actionManager.getActionHandler(IdeActions.ACTION_EDITOR_CLONE_CARET_BELOW); + actionHandler.execute(editor, editor.getCaretModel().getCurrentCaret(), anActionEvent.getDataContext()); } + @Override + public void update(@NotNull final AnActionEvent anActionEvent) { + // + } +} +``` After compiling and running the following code sample, one extra caret will be placed in the editor below the current active caret.