📜 ⬆️ ⬇️

We write a plugin for IntelliJ IDEA, add functionality to the code editor

Starting working in IntelliJ IDEA, I discovered the absence of a convenient keyboard shortcut, which I use in Eclipse - Ctrl + Alt + Up. For this combination, the selected text block or line is copied upwards with moving the cursor to the beginning of the copied block.
In Idea, there is a default action on Ctrl + D that copies the block down (Ctrl + Alt + Down to Eclipse), but you cannot add a similar action up. After Google was asked a question in Q & A, unanswered. Issued on jetbrains. All these actions did not give an answer, so it was decided to write a small plugin for Idea.

Start


First you should download the source code for the IDE version community, since It will take a lot of time, the total size is about 1.6 GB.
Git repository:
git://git.jetbrains.org/idea/community.git

Action is optional, but very desirable, because here we will find java docks of classes and methods of interest to us, as well as the source codes of ready-made plug-ins (almost all the code below I have looked into them).

Project creation


In general, the development of the plugin does not require anything other than IntelliJ IDEA. I used the commercial version, so all actions are carried out further on it. There should be no significant differences from the editorial community.
Create a plugin project: File -> New Project ...
Selecting IntelliJ Platform Plugin

If the Project SDK is missing, click New ... and specify the folder where Idea is installed.
Click Finish.

Adding java docks


Optional step.
After downloading the IDE sources, click File -> Project Structure ... and on the Sourcepath tab, specify the path to the sources:

Now the development and debug of the plugin will be easier.
For example, it was:

has become:

')

Plugin structure


You can read about the structure of the plug-in in Idea here .
Any plug-in for Idea is a .jar file that contains the plugin.xml configuration file in the META-INF folder and the code responsible for the plug-in.

It is necessary to fill in some data in plugin.xml. At this stage, there is nothing difficult to fill out.
plugin.xml
 <idea-plugin version="2"> <id>org.idea.plugin.duplicatelines</id> <name>Duplicate lines</name> <version>1.0</version> <vendor email="test@yourcompany.com">mobileDeveloper</vendor> <description><![CDATA[ Plugin for intellij idea to allow copy lines<br> and block of code like Eclipse IDE (Ctrl+Alt+Up and Ctrl+Alt+Down). ]]></description> <idea-version since-build="107.105"/> <actions></actions> <extensions defaultExtensionNs="com.intellij"> <!-- Add your extensions here --> </extensions> </idea-plugin> 


Actions


In Idea, the so-called Action System works. It allows plugins to add their actions to the menu, to the toolbar, etc. Actions are organized into groups, which in turn may contain other groups. Each Action has a unique identifier. Most standard identifiers are defined in the IdeActions.java file .

Action is a regular java class that inherits from the abstract class AnAction . We will inherit from more specific EditorAction .
Action can be created through the graph. interface: pr pr. mouse on package -> New -> Action:

Having selected the necessary group, if necessary, you can set a key combination to the new Action, a class will be created inherited from AnAction , and in plugin.xml, a description of the Action class will be added to the <actions /> section.
Give the name to our Action class - CopyLineUpAction.
Now inside the tag of the plugin.xml file will be the following code:
Action Description
 <actions> <action id="CopyLineUpAction" class="org.idea.plugin.duplicatelines.CopyLineUpAction" text="Copy line(s) up." description="Copy line(s) up."> <add-to-group group-id="EditorActions" anchor="last"/> <keyboard-shortcut first-keystroke="control alt UP" keymap="$default"/> </action> </actions> 


Please note that we have defined the default keyboard shortcut Ctrl + Alt + Up. I used the standard Eclipse combination because got used to it. In the Idea settings, this combination can be overridden.

Code


If you used gui to create an Action, then the CopyLineUpAction class is already present in the specified package, otherwise you need to create it manually.
The logic of our Action is very simple: by pressing a key combination, define a copied piece of text, paste this text above the current line and move the cursor to the beginning of the copied block.
Actually, the CopyLineUpAction code itself is a bit of it and, in my opinion, it is quite clear. I will add only that the Action class must contain a constructor without parameters (the default constructor):
CodeLineUpAction.java
 package org.idea.plugin.duplicatelines; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.editor.*; import com.intellij.openapi.editor.actionSystem.EditorAction; import com.intellij.openapi.editor.actionSystem.EditorActionHandler; import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler; import com.intellij.openapi.util.TextRange; public class CopyLineUpAction extends EditorAction { public CopyLineUpAction(EditorActionHandler defaultHandler) { super(defaultHandler); } public CopyLineUpAction() { this(new UpHandler()); } private static class UpHandler extends EditorWriteActionHandler { private UpHandler() { } @Override public void executeWriteAction(Editor editor, DataContext dataContext) { Document document = editor.getDocument(); if (editor == null || document == null || !document.isWritable()) { return; } // CaretModel used to find caret position CaretModel caretModel = editor.getCaretModel(); // SelectionModel used to find selection ranges SelectionModel selectionModel = editor.getSelectionModel(); // get the range of the selected characters TextRange charsRange = new TextRange(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd()); // get the range of the selected lines (block of code) TextRange linesRange = new TextRange(document.getLineNumber(charsRange.getStartOffset()), document.getLineNumber(charsRange.getEndOffset())); // range of the duplicated string TextRange linesBlock = new TextRange(document.getLineStartOffset(linesRange.getStartOffset()), document.getLineEndOffset(linesRange.getEndOffset())); // get the string to duplicate String duplicatedString = document.getText().substring(linesBlock.getStartOffset(), linesBlock.getEndOffset()); duplicatedString += "\n"; // insert new duplicated string into the document document.insertString(linesBlock.getStartOffset(), duplicatedString); // select duplicated block editor.getSelectionModel().setSelection(linesBlock.getStartOffset(), linesBlock.getStartOffset()); // move cursor to the start of copied block caretModel.moveToOffset(linesBlock.getStartOffset()); editor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE); } } } 



Debugging


Debug a newly created plugin can be exactly the same as any java application in Idea, with the only difference, in the Run / Debug Configurations -> Add New Configuration window, you will need to specify Plugin. After selecting Run / Debug, a new copy of Idea will be launched with the plugin already installed.
Screenshot


Build and install the plugin


To build a plugin, select Build -> Prepare Plugin Module 'plugin name' For Deployment in the menu. A .jar file will be created in the project directory.
Installation of the pragin is done through File -> Settings ... -> IDE Settings -> Plugins -> Install plugin from disk ...
In the Keymap settings we will see the following line:

Check, enjoy the new functionality.

Upd. Replaced samopisny Range on com. intellij.openapi.util.TextRange , thanks for the hint enDal

useful links


Link to source
Plugin Development Documentation
A lesson on creating a plugin for Idea
Open API and Plugin Development - here you can find the answer to many questions about plugins for Idea.

Source: https://habr.com/ru/post/178217/


All Articles