xzwb / MarkDownNoteYYF

idea插件2020版本

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

MarkDownNoteYYF

idea插件2020版本


项目介绍

本项目名为MarkDownNoteYYF,因为Java学习经常要翻看源码,但是源码是只读文件无法添加注释,所以编写一款插件用来给源码做笔记,并且可以保存为MarkDown格式文件,同时也支持上传到GitHub仓库保存.目前已经发布至JetBrains插件库中 https://plugins.jetbrains.com/plugin/15393-markdownnoteyyf


插件使用

  1. 选中文本,右键点击MarkDownNote

  2. 可以选择添加到已有笔记中,也可以选择创建一个新的笔记列表

  1. 编写笔记,笔记标题:当前笔记的标题;笔记内容:对选中代码段的解释

  1. 点击添加到笔记列表以后,笔记就会添加到noteWindow

  1. 可以再添加一条笔记到当前笔记列表

  1. 创建一个新的笔记列表

  1. 点击保存按钮以后选择保存路径可以生成当前文档标题的MarkDown格式文件

  1. 配置setting中的内容后可以双击上传,即可上传到指定github仓库 文档上传成功会显示
  2. 删除笔记按钮点击后会删除当前笔记列表
  3. 清空按钮点击后会清空当前的笔记列表,但不会删除
  4. 关闭按钮点击后会关闭noteWindow窗口

Ps:笔记在idea关闭后再次打开也会存在

如何申请GitHub Token

点击Setting

点击Developer Settings

选中所有以后,点击确定

保存好Token因为不会再看到了,所以最好复制到文件中

设计模式

  • 建造者模式: 对于NoteData类,有一个NoteDataBuild
public class NoteDataBuilder {
    public static NoteData build(String selectedText, String fileName) {
        NoteData noteData = new NoteData();
        noteData.setSelectedText(selectedText);
        noteData.setFileName(fileName);
        noteData.setFileType(getFileType(fileName));
        return noteData;
    }
    public static NoteData build(Map map) {
        NoteData noteData = new NoteData();
        noteData.setSelectedText((String) map.get("selectedText"));
        noteData.setFileName((String) map.get("fileName"));
        noteData.setFileType((String) map.get("fileType"));
        noteData.setNote((String) map.get("note"));
        noteData.setNoteTitle((String) map.get("noteTitle"));
        return noteData;
    }
}

因为使用Jackson从文件中取出json转换成JavaBean时会转换成LinkedHashMap所以用build()方法传入一个Map构造NoteData对象

  • 模板模式
    • 在使用MarkDown模板的时候,方便添加更多的模板在类cc.yyf.note.procesor.Processorcc.yyf.note.procesor.AbstractFreeMarkProcessorcc.yyf.note.procesor.FreeMarkProcessor
    • Setting页面中添加更多的上传方式,目前只支持GitHub后续可以添加更多的云盘 ,在类cc.yyf.note.window.GitHubUploadSettingViewcc.yyf.note.window.UploadSettingView

技术实现

  • 使用Jackson来保存文档,还有保存笔记列表
["StringSourceCode","IntegerSourceCode"]
{"StringSourceCode":[{"selectedText":"private final byte[] value;","fileName":"String.class","fileType":"class","note":"String底层采用byte[]数组封装","noteTitle":"String底层封装"},{"selectedText":"public String() {\n        this.value = \"\".value;\n        this.coder = \"\".coder;\n    }","fileName":"String.class","fileType":"class","note":"String构造一个空字符串","noteTitle":"String构造"}],"IntegerSourceCode":[{"selectedText":"static final int low = -128;\n        static final int high;\n        static final Integer[] cache;","fileName":"Integer.class","fileType":"class","note":"Integer底层缓存了一个cache数组保存-128到127","noteTitle":"Integer缓存"}]}
  • 实现ApplicationInitializedListener接口,用来在IDEA启动时完成初始化
/**
用来初始化的方法
*/
public void componentsInitialized() {}

同时需要在plugin.xml中配置

<extensions defaultExtensionNs="com.intellij">
        <applicationInitializedListener implementation="cc.yyf.note.init.IDEAInit"/>
    </extensions>
  • 实现了ProjectCloseHandler接口完成了在IDEA关闭时调用的操作
@Override
    public boolean canClose(@NotNull Project project) {
		/**
		返回true可以关闭,false就不能关闭
		*/
        return true;
    }

同样这个也要在plugin.xml中配置

 <extensions defaultExtensionNs="com.intellij">
        <applicationInitializedListener implementation="cc.yyf.note.init.IDEAInit"/>
        <projectCloseHandler implementation="cc.yyf.note.destroy.IDEDestroy"/>
    </extensions>
  • 实现Configurable接口用来在Setting中添加自己的界面
/**
通过返回一个JCompont显示界面
*/
@Override
    public @Nullable JComponent createComponent() {
    }

同样需要在plugin.xml中配置

<extensions defaultExtensionNs="com.intellij">
        <applicationInitializedListener implementation="cc.yyf.note.init.IDEAInit"/>
        <projectCloseHandler implementation="cc.yyf.note.destroy.IDEDestroy"/>
        <applicationConfigurable displayName="MarkDownUpload" instance="cc.yyf.note.window.FirstSettingView">
            <configurable instance="cc.yyf.note.window.GitHubUploadSettingView"/>
        </applicationConfigurable>
    </extensions>

applicationConfigurable可以配置多级页面

  • 通过实现ToolWindowFactory来实现ToolWindow(边边那个noteWindow框)
 @Override
    public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
        // 创建NoteListWindow对象
        NoteListWindow window = new NoteListWindow(project, toolWindow);
        // 将window中的JComboBox实例传出来
        MyComponent.noteToolWindowJComboBox = window.getTextFieldTopic();
        // 获取内容工厂实例
        ContentFactory contentFactory = ContentFactory.SERVICE.getInstance();
        // 获取用于toolWindow显示的内容
        Content content = contentFactory.createContent(window.getContentPanel(), "", false);
        // 给toolWindow设置内容
        toolWindow.getContentManager().addContent(content);
    }

plugin.xml中配置

<extensions defaultExtensionNs="com.intellij">
        <applicationInitializedListener implementation="cc.yyf.note.init.IDEAInit"/>
        <projectCloseHandler implementation="cc.yyf.note.destroy.IDEDestroy"/>
        <!-- Add your extensions here -->
        <toolWindow id = "noteWindow" factoryClass="cc.yyf.note.window.NoteToolWindow" anchor="right"/>
        <applicationConfigurable displayName="MarkDownUpload" instance="cc.yyf.note.window.FirstSettingView">
            <configurable instance="cc.yyf.note.window.GitHubUploadSettingView"/>
        </applicationConfigurable>
    </extensions>
  • 继承AnAction实现一个动作(可以理解为一次点击事件)
 @Override
    public void actionPerformed(AnActionEvent e) {
        // TODO: insert action logic here
    }
<actions>
        <!-- Add your actions here -->
        <action id="PopupMenuActionID" class="cc.yyf.note.action.PopupMenuAction" text="MarkDownNote" description="添加MarkDown笔记">
            <add-to-group group-id="EditorPopupMenu" anchor="first"/>
            <keyboard-shortcut keymap="$default" first-keystroke="ctrl F"/>
        </action>
    </actions>

我的点击事件是EditorPopupMenu.

  • 使用FreeMark模板
## ${topic}
@[toc]
<#list noteList as note>
### ${note.noteTitle}
- ${note.note}
- ${note.fileName}
```${note.fileType}
${note.selectedText}
`` `
</#list>

一些疑惑和BUG和提升空间

  • 没有找到IDEA关闭的时候调用的方法,所以只能使用关闭项目时候调用的方法,导致在直接点击右上角关闭按钮的时候这个方法会调用两次.
  • 可能是线程的一些问题,再点击上传到github按钮的时候,要点击两次才能上传成功.
  • 后续可以开发删除单条笔记和修改笔记排序
  • github上传时不能用中文作为文件名,所以不要使用中文作为文档标题

参考

官方插件开发文档 easy_javadoc源代码

心路历程

一开始面对官方的英文文档看起来是很困难的,还有对于gradle也是第一次使用,以前都是使用maven,对于插件开发也是第一次,API的陌生是开发最大的阻力,很多东西有想法但是很难实现,第一阶段的开发没有上传github也不能支持多个笔记,也不能支持笔记的持久化,IDEA关了笔记就没了,去看了几个插件的实现,用了一个翻译插件,可惜不是用Java开发的后来看了easy_javadoc的源码,知道了如何在Setting中添加页面,加了easy_javadoc作者的开源交流群,群主很热心的解答问题.第二阶段有了上传github功能,但是不支持多笔记,而且不能持久化,于是去看了看Java Swing编程,用Jackson存储将对象转化为json存储在文件中.最终有了现在的项目

About

idea插件2020版本


Languages

Language:Java 99.7%Language:FreeMarker 0.3%