开发也要防沉迷--IDEA插件辅助防沉迷之路

开发也要防沉迷–IDEA插件辅助防沉迷之路

引言

当初年少懵懂,那年夏天填志愿选专业,父母听其他长辈说选择计算机专业好。从那以后,我的身上就有了计院深深的烙印。从寝室到机房,从机房到图书馆,C、C++、Java、只要是想写点自己感兴趣的东西,一坐就是几个小时,但那时年轻,起身,收拾,一路小跑会女神,轻轻松松。

现在工作了,毫无意外的做着开发的工作,长时间久坐。写代码一忙起来就忘了起来活动一下,也不怎么喝水。经常等到忙完了就感觉腰和腿不舒服。直到今年的体检报告一下来,才幡然醒悟:没有一个好身体,就不能好好打工,让老板过上他自己想要的生活了.

开发如何防沉迷???以下是我在工作中见识到的方式:

  1. 定闹钟
  2. 定时喝水水杯
  3. 定时唤醒手环

以上等等,都是定时提醒,那有没有从 源头(IDE) 上来解决呢?譬如,让你的工作环境 (IDE)歇一会 ?最近idea 插件发现了一个有趣的项目 StopCoding 停止代码编写,思想思路尤其的简单,借助这个项目及EOS插件的相关开发经验,这里介绍下IDEA插件开发的相关神级操作。

我们先看下作者实现的效果图:

本文将从以下几个方面来进行IDEA插件开发及stopCoding的实现介绍

    1. IntelliJ IDEA 与 IntelliJ Platform
    1. 开发环境搭建
    1. 开发的一个简单的插件
    1. StopCoding原理及源码解析

一. IntelliJ IDEA 与 IntelliJ Platform

IntelliJ IDEA 简称 IDEA,是 Jetbrains 公司旗下的一款 JAVA 开发工具,支持 Java、Scala、Groovy 等语言的开发,同时具备支持目前主流的技术和框架,擅长于企业应用、移动应用和 Web 应用的开发,提供了丰富的功能,智能代码助手、代码自动提示、重构、J2EE支持、各类版本工具(git、svn等)、JUnit、CVS整合、代码分析、 创新的GUI设计等。

IntelliJ Platform 是一个构建 IDE 的开源平台,基于它构建的 IDE 有 IntelliJ IDEA、WebStorm、DataGrip、以及 Android Studio 等等。IDEA 插件也是基于 IntelliJ Platform 开发的。

二、 开发环境搭建

官方开发文档 IntelliJ Platform SDK

https://plugins.jetbrains.com/docs/intellij/welcome.html

开发工具使用 Intellij IDEA,下载地址:https://www.jetbrains.com/idea/

IDEA 分为两个版本:

  • 社区版(Community):完全免费,代码开源,但是缺少一些旗舰版中的高级特性

  • 旗舰版(Ultimate):30天免费,支持全部功能,代码不开源

开发IDEA的插件推荐使用社区版,因为社区版是开源的,在开发插件的时候,可以调试源代码。

三、开发一个简单的插件

官方文档指导给出了两种开发方式:

3.1 Gradle方式开发插件

一 、Gradle方式新建工程

新建工程目录如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
my_gradle_plugin
├── build.gradle
├── gradle
│ └── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
├── main
│ ├── java
│ └── resources
│ └── META-INF
│ └── plugin.xml
└── test
├── java
└── resources

根目录build.gradle配置内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
plugins {
id 'java'
id 'org.jetbrains.intellij' version '0.6.5'
}

group 'com.your.company'
version '1.0'
sourceCompatibility = 1.8

repositories {
mavenCentral()
}
dependencies {
testImplementation group: 'junit', name: 'junit', version: '4.12'
}

// See https://github.com/JetBrains/gradle-intellij-plugin/
intellij {
version '2020.1'
}
patchPluginXml {
changeNotes """
Add change notes here.<br/>
<em>most HTML tags may be used</em>"""
}

Gradle类型工程Running方式

推荐使用gradle方式开发插件,gradle方式对本地环境要求较低,不需要去配置复杂的sdk等相关内容。

二、DevKit开发模式

启用 Plugin DevKit

Plugin DevKit 是 IntelliJ 的一个插件,它使用 IntelliJ IDEA 自己的构建系统来为开发 IDEA 插件提供支持。开发 IDEA 插件之前需要安装并启用 Plugin DevKit 。

打开 IDEA,导航到 Settings | Plugins,若插件列表中没有 Plugin DevKit,点击 Install JetBrains plugin,搜索并安装。

配置 IntelliJ Platform Plugin SDK

  • 导航到 File | Project Structure,选择对话框左侧栏 Platform Settings 下的 SDKs
  • 点击 + 按钮,先选择 JDK,指定 JDK 的路径;再创建 IntelliJ Platform Plugin SDK,指定 home path 为 IDEA 的安装路径,如图

这里示例用官方action增加一个简单的action作为示例
原地址如下:
https://plugins.jetbrains.com/docs/intellij/working-with-custom-actions.html#developing-the-anaction-methods

1、定义action

定义一个 Java class,继承 AnAction 类,并重写 actionPerformed 方法, 如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class PopupDialogAction extends AnAction {
@Override
public void actionPerformed(@NotNull AnActionEvent event) {
// Using the event, create and show a dialog
Project currentProject = event.getProject();
StringBuffer dlgMsg = new StringBuffer(event.getPresentation().getText() + " Selected!");
String dlgTitle = event.getPresentation().getDescription();
// If an element is selected in the editor, add info about it.
Navigatable nav = event.getData(CommonDataKeys.NAVIGATABLE);
if (nav != null) {
dlgMsg.append(String.format("\nSelected Element: %s", nav.toString()));
}
Messages.showMessageDialog(currentProject, dlgMsg.toString(), dlgTitle, Messages.getInformationIcon());
}
}

2、注册 Action
在 plugin.xml 文件的 元素内注册

1
2
3
4
5
6
7
8
9
10
11
12
13

<action id="org.intellij.sdk.action.PopupDialogAction" class="org.intellij.sdk.action.PopupDialogAction"
text="Action Basics Plugin: Pop Dialog Action" description="SDK action example" icon="SdkIcons.Sdk_default_icon">

<override-text place="MainMenu" text="Pop Dialog Action"/>

<keyboard-shortcut first-keystroke="control alt A" second-keystroke="C" keymap="$default"/>

<mouse-shortcut keystroke="control button3 doubleClick" keymap="$default"/>

<add-to-group group-id="ToolsMenu" anchor="first"/>

</action>

上面示例会定义一个被添加到 IDEA tools菜单的第一个位置(anchor=”first”)添加了”Pop Dialog Action”菜单,点击该菜单将弹出一个 “Action Basics Plugin: Pop Dialog Action Selected!” item,如图

点击该 “Pop Dialog Action” item,弹出一个提示输入名字的对话框

更多 action 信息请移步
IntelliJ Platform Action System

四、StopCoding原理及源码解析

开源地址: https://github.com/jogeen/StopCoding.git

该插件已经上传插件市场,可下载体验:

Step1. 然后在菜单栏中tools->StopCoding

Step2. 设置适合你的参数然后保存。

Step3. 然后快乐的Coding吧,再不用担心自己会沉迷了。工作时间结束,她会弹出下框进行提醒,当然,这个框是关不掉的.只有你休息了足够的时间它才会自动关闭.

工程结构分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
.
├── image
│   ├── step1.png
│   ├── step2.png
│   ├── step3.png
│   └── step.gif
├── LICENSE
├── readme.md
├── readme_ZH.md
├── resources
│   ├── img
│   │   └── stop.png
│   └── META-INF
│   ├── pluginIcon_dark.svg
│   ├── pluginIcon.svg
│   └── plugin.xml
├── src
│   └── icu
│   └── jogeen
│   └── stopcoding
│   ├── data
│   │   ├── DataCenter.java
│   │   └── SettingData.java
│   ├── service
│   │   └── TimerService.java
│   ├── StopCodingSettingAction.java
│   ├── task
│   │   ├── RestTask.java
│   │   └── WorkTask.java
│   └── ui
│   ├── SettingDialog.form
│   ├── SettingDialog.java
│   ├── TipsDialog.form
│   └── TipsDialog.java
└── StopCoding.iml

上图可以看到,工程结构十分的简单,基于devkit模式进行开发

  • data包
    SettingData,配置信息对应model
    DataCenter,作为运行时的数据中心,都是些静态的全局变量
  • service
    TimerService 这个定时计算的核心代码
  • task
    RestTask 休息时的定时任务
    WorkTask 工作时的定时任务
  • ui
    SettingDialog 设置信息的对话框
    TipsDialog 休息时提醒的对话框
    StopCodingSettingAction 启动入口的action

  • plugin.xml
    这是插件工程的核心配置文件,里面每一项的都添加了详细的注释,有疑问的小伙伴可以留言,我们一起探讨.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
<idea-plugin>
<!-- 插件唯一id,不能和其他插件项目重复,所以推荐使用com.xxx.xxx的格式
插件不同版本之间不能更改,若没有指定,则与插件名称相同 -->
<id>icu.jogeen.StopCoding.id</id>
<!-- 插件名称,别人在官方插件库搜索你的插件时使用的名称 -->

<name>StopCoding</name>
<!-- 插件版本号 -->

<version>1.2.1</version>
<!-- 供应商主页和email(不能使用默认值,必须修改成自己的)-->

<vendor email="jogeen@qq.com" url="https://github.com/jogeen/StopCoding">jogeen</vendor>

<!-- 插件的描述 (不能使用默认值,必须修改成自己的。并且需要大于40个字符)-->

<description><![CDATA[
<p>This is a work timer.It can set every working period to remind you that it's time to have a rest, drink some water and exercise your body.
Only in this way can you really work healthily</p>
<ol>
<li>In the tools menu bar, open stopcoding.</li>
<li>Set working hours and rest time, and save them.</li>
<li>When the set time comes, there will be a pop-up box to remind you to rest, so that you can not operate idea temporarily.</li>
</ol>
<hr>
<p>如果你也经常沉迷于写代码,忘了起身休息喝水,那么试试这个插件吧</p>
<ol>
<li>在菜单栏的Tools中,打开StopCoding插件进行设置</li>
<li>设置工作时间和休息时间,并且保存</li>
<li>当设置的时间一到,就会有弹框提醒你休息,让你暂时不能操作idea</li>
</ol>
<p>项目地址:<a href="https://github.com/jogeen/StopCoding">https://github.com/jogeen/StopCoding</p>
]]></description>

<!-- 插件版本变更信息,支持HTML标签;
将展示在 settings | Plugins 对话框和插件仓库的Web页面 -->
<change-notes><![CDATA[
<ul>
<li>V1.2 add icon(Thanks for the icon provided by my good friend Hu Wei).</li>
<li>V1.1 update Guide to use.</li>
<li>V1.0 release.</li>
</ul>
]]>
</change-notes>

<!-- 插件兼容IDEAbuild 号(最低版本号)-->
<idea-version since-build="173.0"/>
<!-- 插件所依赖的其他插件的id -->
<depends>com.intellij.modules.lang</depends>


<extensions defaultExtensionNs="com.intellij">
<!-- 声明该插件对IDEA core或其他插件的扩展 -->

</extensions>

<!-- 编写插件动作 -->
<actions>
<action id="StopCoding_setting_id" class="icu.jogeen.stopcoding.StopCodingSettingAction" text="StopCoding"
description="setting">
<add-to-group group-id="ToolsMenu" anchor="first"/>
<keyboard-shortcut keymap="$default" first-keystroke="ctrl S" second-keystroke="C"/>
</action>
</actions>

</idea-plugin>

从public.xml可以看出,这个插件比较简单,只有一个StopCoding_setting_id配置项,入口类也是

icu.jogeen.stopcoding.StopCodingSettingAction

1
2
3
4
5
6
7
8
public class StopCodingSettingAction extends AnAction {

@Override
public void actionPerformed(AnActionEvent e) {
SettingDialog settingDialog = new SettingDialog();
settingDialog.setVisible(true);
}
}

源码中只是展示了SettingDialog,基于Swing画了一个可视化界面.

icu.jogeen.stopcoding.ui.SettingDialog

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//绑定确定按钮事件
buttonOK.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onOK();
}
});
//绑定取消按钮事件
buttonCancel.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onCancel();
}
});
//绑定关闭按钮事件
setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
onCancel();
}
});
contentPane.registerKeyboardAction(new ActionListener() {
public void actionPerformed(ActionEvent e) {
onCancel();
}
}, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
//绑定启用选择按钮时间
openRbtn.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
openRbtn.setText(openRbtn.isSelected() ? "Running" : "Stopped");
}
});

在SettingDialog中对事件进行了监听,其主要思路就是schedule去添加一个定时任务,和使用cancel去取消任务停止定时器。然后弹出一个dialog阻止持续coding.

最后:

相信有了这些基本介绍,感谢兴趣的小伙伴想去看看源码和尝试自己写一个小插件就没什么大问题了。希望这个插件能帮到作为程序员得你,和这篇文章对你有一点点启发。当然麻烦小伙伴点个赞,鼓励一下打工人。