Sometimes it is a nice thing to extend an editor to have it do some new stuff, like being able to revert an open file to its state on disk. In this post I’m going to quickly demonstrate how to start and finish a plugin to extend theIntelliJ IDEA editor from Jetbrains. These instructions will work if you have the Ultimate or Community edition, and you can make the plugin available for all IntelliJ based editors including WebStorm, PyCharm, RubyMine and PHPStorm.

Whether you can finish these instructions under 30 minutes depends on your internet connection speed, because you have to do a git clone of the IntelliJ Community Edition source code, and that’s a lot of stuff to download.

At my current employer Floobits we are working on an IntelliJ plugin, and through that process I have learned most of this.

System requirements

OS: I have developed plugins for IntelliJ on both Mac OS X and Windows and the steps are the same.

Java: JDK 6 works, JDK 7 might not. I compile with a Java 1.6 JDK.

HD space: Lots of space for multiple copies of IntelliJ IDEA and its source code.

Getting the environment set up.

Resource: Official Jetbrain instructions

Step 1: Download and install Community Edition of IntelliJ IDEA

The first step, is to download and install the Community version of IntelliJ IDEA if you don’t already have it. Even if you have the Ultimate version of IntelliJ IDEA, you will need the Community version. This is because the Ultimate version is closed source and when you’re debugging it is nice to be able to see the source and definitions for IntelliJ resources. Note I still use the Ultimate version of IntelliJ IDEA (version 13) to develop the plugin. I debug and test the plugin using the Community version.

Remember the path to where the Community Edition was installed to, you’ll need this in a moment.

Step 2: Do a shallow git clone of the IntelliJ IDEA Community Edition source code

git clone --depth 1 https://github.com/JetBrains/intellij-community.git

This step will take the longest because it takes forever to do a git clone of the IntelliJ source code. Thus do a shallow git clone using –depth 1 in the command. This is really simple on a Mac or any *nix based system, just use git clone –depth 1. On Windows I used Atlassian’s SourceTree which allows you to specify the depth in the GUI. A depth of 1 reduces the download because the history is truncated to a depth of 1. If you do not do this step, downloading the source code will take you days.

Step 3: Create a project and set up your project structure.

Create a project

Fire up the version of IntelliJ that you want to use to write code. This can be either of the Ultimate or Community versions. Create a new project. Name it whatever you want to call your plugin. I’m going to call mine DiskRead.

Set up the SDK

If you already have a Java JDK skip this paragraph. If you don’t have one already, you’ll have to get a Java JDK. Somewhere or other on the Jetbrains site it recommends Java 1.6, but Oracle will warn you that it is out of date. I have had problems using the JDK 7 when interacting with Intellij jar files compiled with 1.6. Once you have downloaded a Java JDK, you’ll need to create an SDK for this in IntelliJ IDEA even though we will not use it directly. In the project structure dialog that appears after you create a new project, create a new SDK for the version of Java you downloaded similar to the step below, only you’ll be giving it the path to where you installed the Java JDK.

Setup a Plugin SDK by clicking the “new” button next to the Project SDK:

Note that the SDK setup project structure dialog looks a little different on Windows.

It will prompt you to locate the Comunity Edition that you installed. You are not to give it the path to the source you downloaded, this step requires the path to the Community Edition of IntelliJ that you installed in the first step. On a Mac the path for this is:

/Applications/IntelliJ IDEA 13 CE.app

On Windows the path was:

C:\\Program Files (x86)\JetBrains\IntelliJ IDEA Community Edition 13.0.1

Click finish if you are happy with where it will create the project, but you are not yet done setting things up.

You should now see a project window for the project you just created. Go to File->Project Structure from the menu. On a mac you can just hit ⌘+; on Windows it’s Cntrl+Alt+Shift+S. On the left side, click on “SDKs” and check out the classpath tab:

Next click on the sourcepath tab:

Here you’ll add the path to the shallow git clone for the IntelliJ Community edition source you checked out. Click the plus button at the bottom. Find the path in the dialog that appears. Click OK, then you should see a bunch of classes were added. Click apply and ok.

We are still not done settings everything up. Next you’ll want to set up a build and debug configuration. From the top menu go to Run -> Edit configurations:

Give the build configuration a name, it’s not important what it is. I also recommend checking “Show idea.log” because it gives you a nice tab in the debug window to show you info and warning statements.

Congratulations, you are now all done setting up!

Developing the plugin

Resources

IntelliJ IDEA Plugin Development Guide

Plugin Development FAQ

IntelliJ IDEA Architectural Overview

Making it work.

So now that the environment is all set up, in order to get my file to reflect the state on disk I need to create an action. First thing is to use the GUI to create a new action:

So I right click on src in the project sidebar and click “new” and then click “Action.” This will lead to a dialog to create a new Action. You give it a name, an id, a class name, a helpful description and then assign it to a group which will tell IntelliJ where to put this action. Actions don’t have to be a part of groups, and you can even make buttons that go into the project UI, but in this case I just want it to be in the “toolbar” menu like so:

You can also assign keyboard shortcuts, as I did.

Once you’re all done there click OK and two things should have happened:

  1. Your plugin.xml should be updated to reflect your new action. You can see this XML file by selecting it from within the META-INF directory in your project sidebar. You should see your action in the actions section.

  2. A new class called ReadCurrentFile was created.

For me the new class looks like this:

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
/**
* User: bjorn
* Date: 1/29/14
* Time: 12:28 PM
*/
public class ReadCurrentFile extends AnAction {
public void actionPerformed(AnActionEvent e) {
// TODO: insert action logic here
}
}

I do some little magic coding and write the code to get my plugin to do what I want:

import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.sun.org.apache.bcel.internal.generic.NEW; import java.io.*;
import java.util.regex.Pattern; /**
* User: bjorn
* Date: 1/29/14
* Time: 12:28 PM
*/
public class ReadCurrentFile extends AnAction {
public void actionPerformed(AnActionEvent e) {
final Project project = e.getProject();
if (project == null) {
return;
}
Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor();
if (editor == null) {
return;
}
final Document document = editor.getDocument();
if (document == null) {
return;
}
VirtualFile virtualFile = FileDocumentManager.getInstance().getFile(document);
if (virtualFile == null) {
return;
}
final String contents;
try {
BufferedReader br = new BufferedReader(new FileReader(virtualFile.getPath()));
String currentLine;
StringBuilder stringBuilder = new StringBuilder();
while ((currentLine = br.readLine()) != null) {
stringBuilder.append(currentLine);
stringBuilder.append("\n");
}
contents = stringBuilder.toString();
} catch (IOException e1) {
return;
}
final Runnable readRunner = new Runnable() {
@Override
public void run() {
document.setText(contents);
}
};
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().runWriteAction(readRunner);
}
}, "DiskRead", null);
}
});
}
}

This basically does one thing: When the action is run (like by selecting it from the tools menu), it reads the current file from disk and updates it. It does this by getting the current active editor from the project, then getting the document from it, using that to get the VirtualFile and then using a plain old Java File to read the contents from disk. Reading from the VirtualFile would accomplish nothing, as that is the cached content that I’m trying to replace from disk.

The runnables and invoke later nested classes you see there are required by IntelliJ. It’s very verbose, but basically you can’t write a file in the main thread, it needs to be done in a runWriteAction which requires an invokeLater. If you want to read from VirtualFiles and documents you’d need to run that in a similar runReadAction. IntelliJ will scream at you at runtime if you forget to do this.

The last thing I do is update the document with setText. Internally IntelliJ documents represent new lines with the unixy “\n” line ending in all cases. Attempting to use a carriage return will result in an assertion error. So thus I append all new lines to the StringBuffer as “\n” instead of what they originally were and any carriage returns will be replaced with new lines. When IntelliJ writes files to disk, it will use the type of new line characters you have selected in your preferences, but internally it is always “\n”.

Testing it

Finally, I click Run->Debug and IntelliJ will spawn a second IntelliJ instance which will have my plugin installed. I open up a dummy project, write some text into a file without saving it (note I have all automated saves disabled in my settings), and then go to the Tools menu to select my action. I see it runs, and removed all the text I added into the file.

Deploying

Now that I’m all done I want to tell the world about it and install it myself. For that, go back to your regular IntelliJ and go to Build ->Prepare Plugin Module “DiskRead” For Deployment

This may create either a zip file or a jar file. You can install this new file right into your IntelliJ by opening up settings and going to plugin and clicking the “Install from Disk” or you can go ahead and get your plugin up on the officialJetbrains plugin repository.

Final note

If you want your plugin to work in PyCharm or RubyMine or any of the other IntelliJ based editors you need to uncomment a line in your plugin.xml.

Change this:

  <!-- uncomment to enable plugin in all products
<depends>com.intellij.modules.lang</depends>
-->

To this:

  <depends>com.intellij.modules.lang</depends>

I put the source code in a GitHub repo:

https://github.com/btipling/DiskRead/

Any errors or comments, please send to @bjorntipling

How to make an IntelliJ IDEA plugin in less than 30 minutes的更多相关文章

  1. Intellij MyBatisPlus Plugin插件破解

    1. 下载原始的MyBatisPlus Plugin插件. 2. 下载替换包,请根据实际版本下载: https://github.com/myoss/profile/tree/master/idea/ ...

  2. 从零开始编写IntelliJ IDEA插件

    写Java代码的时候,经常会涉及到重复性的操作,这个时候就会想要是有这样一个插件就好了,如果是大家都会遇到的场景,IDE或许已经提供了,再不然也有可能有人编写了相关的插件.要是这个操作是你们的编码环境 ...

  3. IntelliJ IDEA手工安python装插件方法

    IntelliJ IDEA手工安装插件方法 以IntelliJ IDEA 11.0.1安装python为例: (1)下载python插件地址:http://plugins.intellij.net/p ...

  4. 在IntelliJ IDEA14中安装go语言插件

    go语言的集成开发环境仍不成熟,试用了liteide,感觉很不适应,弹出菜单对程序员的干扰太大.所以就试大牌的IntelliJ IDEA,这工具本来是JAVA开发阵营的,不过它已经变为一个非常强大的支 ...

  5. 安装IntelliJ IDEA JetGroovy(转)

    JetGroovy是一个免费而且开源的专用于支持Groovy和Grails的IntelliJ IDEA插件.这个插件是由JetBrains公司自己开发的,对于Groovy语言和Web框架都提供了无以伦 ...

  6. intellij idea该插件开发摘要

    最近在做一个intellij idea插件,功能是读取表和数据库信息字段和预先定义的模板来生成代码文件(实体,service,springmvc该controller,freemark文件等). 找了 ...

  7. intellij idea 插件开发--快速定位到mybatis mapper文件中的sql

    intellij idea 提供了openApi,通过openApi我们可以自己开发插件,提高工作效率.这边直接贴个链接,可以搭个入门的demo:http://www.jianshu.com/p/24 ...

  8. IntelliJ IDEA Configuring projects

    https://www.jetbrains.com/help/idea/configuring-projects.html Configuring projects A project in Inte ...

  9. Intellij IDEA 插件开发秘籍

    来这里找志同道合的小伙伴! 这里总结一下 Intellij IDEA 插件开发的知识,供大家参考,本篇文章包含以下内容: 开发环境搭建 Component 介绍 Extension Point And ...

随机推荐

  1. java 类字面常量,泛化的Class引用

    类名.class 就是字面常量,代表的就是该类的Class对象引用.常量需要赋值给变量 简单,安全. 编译期接受检查,不需要像forName一样置于try/catch块中. 加载后不会进行初始化,初始 ...

  2. PHP获取文件后缀名

    PHP获取文件后缀名是PHP学习者常见的一种操作,无论是在面试过程中还是PHP新手自学中.PHP获取文件后缀名都是很普遍的需要掌握的一个知识点. 下面我们就给大家总结介绍PHP获取文件扩展名也就是后缀 ...

  3. hdu1069线性dp

    /* dp[i]:取第i个方块时最多可以累多高 */ #include<bits/stdc++.h> using namespace std; struct node{ int x,y,z ...

  4. cf276E 两棵线段树分别维护dfs序和bfs序,好题回头再做

    搞了一晚上,错了,以后回头再来看 /* 对于每次更新,先处理其儿子方向,再处理其父亲方向 处理父亲方向时无法达到根,那么直接更新 如果能达到根,那么到兄弟链中去更新,使用bfs序 最后,查询结点v的结 ...

  5. Intellij IDEA配置tomcat热部署

    idea2017+tomcat8为本文的实验环境 1.打开tomcat的edit configuration,一定要选择war exploded  在idea tomcat 中server的配置里,有 ...

  6. 步步为营-30-AES加密与解密

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  7. webstrom的热更新没效果

    webstorm保存的时候会先保存到临时文件中,其实并没有真正保存,要在setting->stystem settings下的“use save write”去掉

  8. PHP 三元运算 ??与?:

    //$c = $a ?? $b; 等效 $c = isset($a) ? $a : $b; //$c = $a ?: $b; 等效 $c = $a ? $a : $b; $a = 'a'; $b = ...

  9. 6-9 天平 uva839

    这题十分巧妙!!代码精简!强大的递归!!! 边读边判断   先读到底部  慢慢往上判断   难点在于传递w1+w2 有一个比LRJ更加简便的方法  return传递  全局变量判断 #include ...

  10. Unity 中几点注意的地方

    1.面板摆放的规范 2.project工程面板中 文件夹命名的规范,不同类型的东西要分类摆放,例如Script 3.不要留空函数体(系统自动生成Start, Uadate等),空函数体一样会执行,尤其 ...