├── .gitignore
├── src
└── cn
│ └── neday
│ └── excavator
│ ├── service
│ ├── WatchService.kt
│ └── WatchServiceImpl.kt
│ ├── checker
│ ├── ICheck.kt
│ └── ProjectChecker.kt
│ ├── action
│ ├── kill
│ │ ├── KillFlutterAction.kt
│ │ ├── KillGradleAction.kt
│ │ └── BaseKillAction.kt
│ ├── generation
│ │ ├── BuildAction.kt
│ │ ├── CleanAction.kt
│ │ ├── WatchAction.kt
│ │ ├── RebuildAction.kt
│ │ └── BaseGenerationAction.kt
│ └── BaseAction.kt
│ ├── tool
│ ├── ConsoleToolFactory.form
│ └── ConsoleToolFactory.java
│ └── setting
│ ├── Setting.form
│ └── Setting.java
├── release
├── build-runner-helper_1.0.jar
├── build-runner-helper_1.1.jar
├── build-runner-helper_1.2.jar
├── build-runner-helper_1.3.jar
├── build-runner-helper_1.4.jar
├── build-runner-helper_1.5.jar
├── build-runner-helper_1.6.jar
├── build-runner-helper_1.7.jar
├── build-runner-helper_1.8.jar
└── build-runner-helper_1.9.jar
├── resources
├── icons
│ ├── ic_kill_flutter.svg
│ ├── ic_clean.svg
│ ├── ic_build.svg
│ ├── ic_kill_gradle.svg
│ ├── ic_watch.svg
│ ├── ic_rebuild.svg
│ └── ic_excavator.svg
└── META-INF
│ ├── pluginIcon.svg
│ └── plugin.xml
├── LICENSE
├── README_CN.md
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | /out
3 | /*.iml
4 | /*.jar
5 |
--------------------------------------------------------------------------------
/src/cn/neday/excavator/service/WatchService.kt:
--------------------------------------------------------------------------------
1 | package cn.neday.excavator.service
2 |
3 | interface WatchService
--------------------------------------------------------------------------------
/src/cn/neday/excavator/service/WatchServiceImpl.kt:
--------------------------------------------------------------------------------
1 | package cn.neday.excavator.service
2 |
3 | class WatchServiceImpl : WatchService
--------------------------------------------------------------------------------
/release/build-runner-helper_1.0.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/HEAD/release/build-runner-helper_1.0.jar
--------------------------------------------------------------------------------
/release/build-runner-helper_1.1.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/HEAD/release/build-runner-helper_1.1.jar
--------------------------------------------------------------------------------
/release/build-runner-helper_1.2.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/HEAD/release/build-runner-helper_1.2.jar
--------------------------------------------------------------------------------
/release/build-runner-helper_1.3.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/HEAD/release/build-runner-helper_1.3.jar
--------------------------------------------------------------------------------
/release/build-runner-helper_1.4.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/HEAD/release/build-runner-helper_1.4.jar
--------------------------------------------------------------------------------
/release/build-runner-helper_1.5.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/HEAD/release/build-runner-helper_1.5.jar
--------------------------------------------------------------------------------
/release/build-runner-helper_1.6.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/HEAD/release/build-runner-helper_1.6.jar
--------------------------------------------------------------------------------
/release/build-runner-helper_1.7.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/HEAD/release/build-runner-helper_1.7.jar
--------------------------------------------------------------------------------
/release/build-runner-helper_1.8.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/HEAD/release/build-runner-helper_1.8.jar
--------------------------------------------------------------------------------
/release/build-runner-helper_1.9.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/HEAD/release/build-runner-helper_1.9.jar
--------------------------------------------------------------------------------
/src/cn/neday/excavator/checker/ICheck.kt:
--------------------------------------------------------------------------------
1 | package cn.neday.excavator.checker
2 |
3 | interface ICheck {
4 | /**
5 | * 校验方法
6 | *
7 | * @param path 待检查路径
8 | * @return 校验结果,true 为 通过
9 | */
10 | fun check(path: String?): Boolean
11 | }
--------------------------------------------------------------------------------
/src/cn/neday/excavator/action/kill/KillFlutterAction.kt:
--------------------------------------------------------------------------------
1 | package cn.neday.excavator.action.kill
2 |
3 | class KillFlutterAction : BaseKillAction() {
4 | override val killWhat = "Flutter"
5 | override val processNameOnUnix = "flutter"
6 | override val processWhereOnUnixOnWindows = "commandline name='flutter'"
7 | }
--------------------------------------------------------------------------------
/src/cn/neday/excavator/action/kill/KillGradleAction.kt:
--------------------------------------------------------------------------------
1 | package cn.neday.excavator.action.kill
2 |
3 | class KillGradleAction : BaseKillAction() {
4 | override val killWhat = "Gradle"
5 | override val processNameOnUnix = "gradle-launcher"
6 | override val processWhereOnUnixOnWindows = "commandline like '%gradle-launcher%' and name like '%java%'"
7 | }
--------------------------------------------------------------------------------
/src/cn/neday/excavator/action/generation/BuildAction.kt:
--------------------------------------------------------------------------------
1 | package cn.neday.excavator.action.generation
2 |
3 | class BuildAction : BaseGenerationAnAction() {
4 | override val cmd = "packages pub run build_runner build"
5 | override val title = "Building"
6 | override val successMessage = "Complete!\nRunning build successfully."
7 | override val errorMessage = "Could not running build!"
8 | }
--------------------------------------------------------------------------------
/src/cn/neday/excavator/action/generation/CleanAction.kt:
--------------------------------------------------------------------------------
1 | package cn.neday.excavator.action.generation
2 |
3 | class CleanAction : BaseGenerationAnAction() {
4 | override val cmd = "packages pub run build_runner clean"
5 | override val title = "Cleaning"
6 | override val successMessage = "Complete!\nRunning clean successfully."
7 | override val errorMessage = "Could not running clean!"
8 | }
--------------------------------------------------------------------------------
/src/cn/neday/excavator/action/generation/WatchAction.kt:
--------------------------------------------------------------------------------
1 | package cn.neday.excavator.action.generation
2 |
3 | class WatchAction : BaseGenerationAnAction() {
4 | override val cmd = "packages pub run build_runner watch"
5 | override val title = "Watching"
6 | override val successMessage = "Complete!\nRunning watch successfully."
7 | override val errorMessage = "Could not running watch!"
8 | }
--------------------------------------------------------------------------------
/src/cn/neday/excavator/action/generation/RebuildAction.kt:
--------------------------------------------------------------------------------
1 | package cn.neday.excavator.action.generation
2 |
3 | class RebuildAction : BaseGenerationAnAction() {
4 | override val cmd = "packages pub run build_runner build --delete-conflicting-outputs\n"
5 | override val title = "Rebuilding"
6 | override val successMessage = "Complete!\nRunning rebuild successfully."
7 | override val errorMessage = "Could not running rebuild!"
8 | }
--------------------------------------------------------------------------------
/resources/icons/ic_kill_flutter.svg:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/src/cn/neday/excavator/checker/ProjectChecker.kt:
--------------------------------------------------------------------------------
1 | package cn.neday.excavator.checker
2 |
3 | import java.io.File
4 | import java.util.*
5 |
6 | class ProjectChecker : ICheck {
7 |
8 | private var checkFiles: ArrayList = arrayListOf("lib", ".metadata", ".packages", "pubspec.lock", "pubspec.yaml")
9 |
10 | override fun check(path: String?): Boolean {
11 | if (path == null || path.isEmpty()) {
12 | return false
13 | }
14 | val dir = File(path)
15 | if (!dir.exists() || !dir.isDirectory) {
16 | return false
17 | }
18 | val files = Objects.requireNonNull(dir.list())
19 | var count = 0
20 | for (file in files) {
21 | if (checkFiles.contains(file)) {
22 | count++
23 | }
24 | }
25 | return count == checkFiles.size
26 | }
27 | }
--------------------------------------------------------------------------------
/resources/icons/ic_clean.svg:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/resources/icons/ic_build.svg:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 苏晟
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/cn/neday/excavator/action/BaseAction.kt:
--------------------------------------------------------------------------------
1 | package cn.neday.excavator.action
2 |
3 | import cn.neday.excavator.checker.ProjectChecker
4 | import com.intellij.openapi.actionSystem.AnAction
5 | import com.intellij.openapi.actionSystem.AnActionEvent
6 | import com.intellij.openapi.actionSystem.PlatformDataKeys
7 | import com.intellij.openapi.ui.Messages
8 |
9 |
10 | abstract class BaseAnAction : AnAction() {
11 |
12 | override fun update(event: AnActionEvent) {
13 | val project = event.getData(PlatformDataKeys.PROJECT)
14 | val projectPath = project?.basePath
15 | event.presentation.isEnabledAndVisible = ProjectChecker().check(projectPath)
16 | }
17 |
18 | protected fun isWindowsOS(): Boolean {
19 | return System.getProperty("os.name").toLowerCase().startsWith("windows")
20 | }
21 |
22 | protected fun showInfo(message: String) {
23 | Messages.showMessageDialog(message, "Flutter Build Runner Helper", Messages.getInformationIcon())
24 | }
25 |
26 | protected fun showErrorMessage(message: String) {
27 | Messages.showMessageDialog(message, "Flutter Build Runner Helper", Messages.getErrorIcon())
28 | }
29 | }
--------------------------------------------------------------------------------
/src/cn/neday/excavator/tool/ConsoleToolFactory.form:
--------------------------------------------------------------------------------
1 |
2 |
27 |
--------------------------------------------------------------------------------
/resources/icons/ic_kill_gradle.svg:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/resources/icons/ic_watch.svg:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/src/cn/neday/excavator/setting/Setting.form:
--------------------------------------------------------------------------------
1 |
2 |
43 |
--------------------------------------------------------------------------------
/resources/icons/ic_rebuild.svg:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/README_CN.md:
--------------------------------------------------------------------------------
1 | # [Flutter-Build-Runner-Helper](https://plugins.jetbrains.com/plugin/14442-flutter-build-runner-helper)
2 |
3 | [](https://opensource.org/licenses/MIT)
4 |
5 | ### [English Document](https://github.com/nEdAy/Flutter-Build-Runner-Helper/blob/master/README.md)
6 |
7 | 一个Android Studio的插件(IntelliJ IDEA),加速你的日常Flutter开发。 Flutter build_runner 助手,使执行build_runner命令更简单。
8 |
9 | > **如果你觉得这个工具对你有用,随手给个 Star,让我知道它是对你有帮助的,我会继续更新和维护它。**
10 |
11 | ### 功能
12 |
13 | Adds the following build_runner commands to Android Studio:
14 |
15 | - Build : flutter packages pub run build_runner build
16 | - Rebuild : flutter packages pub run build_runner build --delete-conflicting-outputs
17 | - Watch : flutter packages pub run build_runner watch
18 | - Clean : flutter packages pub run build_runner clean
19 |
20 | - Kill Gradle : Kill Gradle if a current task is running
21 | - Kill Flutter : Kill Flutter if a current task is running
22 |
23 | There are two basic ways to invoke a command:
24 |
25 | - Click the action button in the Toolbar.
26 | - Use the shortcut key.
27 |
28 | ### 使用方法
29 |
30 | Option 0: Search the Plugins Marketplace for the 'Flutter Build Runner Helper' and install it.
31 |
32 | Option 1: Open this [link](https://plugins.jetbrains.com/plugin/14442-flutter-build-runner-helper) and install to IDE.(
33 | Compatible with IntelliJ IDEA, Android Studio, WebStorm)
34 |
35 | Option 2: Download the latest JAR package in the release folder and manually 'Install Plugin from Disk...'.
36 |
37 | ### MIT License
38 |
39 | Copyright (c) 2021 苏晟
40 |
41 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
42 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
43 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
44 | persons to whom the Software is furnished to do so, subject to the following conditions:
45 |
46 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
47 | Software.
48 |
49 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
50 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
51 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
52 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [Flutter-Build-Runner-Helper](https://plugins.jetbrains.com/plugin/14442-flutter-build-runner-helper)
2 |
3 | ## [2.0.0] has migrated to [Flutter - Toolkit](https://github.com/nEdAy/Flutter-Toolkit)
4 | ## [2.0.0] 已经迁移到 [Flutter-Toolkit](https://github.com/nEdAy/Flutter-Toolkit)
5 |
6 | [](https://opensource.org/licenses/MIT)
7 |
8 | [Download Link - 下载地址](https://plugins.jetbrains.com/plugin/14442-flutter-build-runner-helper)
9 |
10 | ### [中文文档](https://github.com/nEdAy/Flutter-Build-Runner-Helper/blob/master/README_CN.md)
11 |
12 | A plugin for Android Studio(IntelliJ IDEA) that speeds up your day-to-day flutter development. Flutter Build Runner
13 | Helper, to make it easier to execute build_runner commands.
14 |
15 | ### Feature
16 |
17 | Adds the following build_runner commands to Android Studio(IntelliJ IDEA):
18 |
19 | - Build : flutter packages pub run build_runner build
20 | - Rebuild : flutter packages pub run build_runner build --delete-conflicting-outputs
21 | - Watch : flutter packages pub run build_runner watch
22 | - Clean : flutter packages pub run build_runner clean
23 |
24 | - Kill Gradle : Kill Gradle if a current task is running
25 | - Kill Flutter : Kill Flutter if a current task is running
26 |
27 | There are two basic ways to invoke a command:
28 |
29 | - Click the action button in the Toolbar.
30 | - Use the shortcut key.
31 |
32 | ### Instruction manual
33 |
34 | Option 0: Search the Plugins Marketplace for the 'Flutter Build Runner Helper' and install it.
35 |
36 | Option 1: Open this [link](https://plugins.jetbrains.com/plugin/14442-flutter-build-runner-helper) and install to IDE.(
37 | Compatible with IntelliJ IDEA, Android Studio, WebStorm)
38 |
39 | Option 2: Download the latest JAR package in the release folder and manually 'Install Plugin from Disk...'.
40 |
41 | ### MIT License
42 |
43 | Copyright (c) 2021 苏晟
44 |
45 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
46 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
47 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
48 | persons to whom the Software is furnished to do so, subject to the following conditions:
49 |
50 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
51 | Software.
52 |
53 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
54 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
55 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
56 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
57 |
--------------------------------------------------------------------------------
/src/cn/neday/excavator/setting/Setting.java:
--------------------------------------------------------------------------------
1 | package cn.neday.excavator.setting;
2 |
3 | import com.intellij.ide.util.PropertiesComponent;
4 | import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
5 | import com.intellij.openapi.options.Configurable;
6 | import com.intellij.openapi.ui.TextFieldWithBrowseButton;
7 | import org.jetbrains.annotations.Nls;
8 | import org.jetbrains.annotations.Nullable;
9 |
10 | import javax.swing.*;
11 |
12 | public class Setting implements Configurable {
13 | private JPanel mMainPanel;
14 | private JLabel mTitle;
15 | private TextFieldWithBrowseButton mButton;
16 | private JLabel mHint;
17 | private String _lastValue;
18 |
19 | public static final String FLUTTER_PATH_KEY = "flutter_path";
20 |
21 | /**
22 | * 在settings中显示的名称
23 | *
24 | * @return 名称
25 | */
26 | @Nls(capitalization = Nls.Capitalization.Title)
27 | @Override
28 | public String getDisplayName() {
29 | return "Flutter Build Runner Helper";
30 | }
31 |
32 | @Override
33 | public String getHelpTopic() {
34 | return null;
35 | }
36 |
37 | /**
38 | * 初始化控件
39 | *
40 | * @return mMainPanel
41 | */
42 | @Override
43 | public @Nullable JComponent createComponent() {
44 | mTitle.setText("Flutter Path");
45 | boolean isWindows = System.getProperty("os.name").toLowerCase().startsWith("windows");
46 | String flutterName = isWindows ? "flutter.bat" : "flutter";
47 | String hintWord = "Please choose your flutter, maybe it path is '../../flutter/bin/" + flutterName + "'.";
48 | mHint.setText(hintWord);
49 | PropertiesComponent propertiesComponent = PropertiesComponent.getInstance();
50 | String flutterPath = propertiesComponent.getValue(FLUTTER_PATH_KEY);
51 | mButton.setText(flutterPath);
52 | _lastValue = flutterPath;
53 | mButton.addBrowseFolderListener("Choose Your Flutter", hintWord, null,
54 | FileChooserDescriptorFactory.createSingleFileDescriptor().withFileFilter(virtualFile -> {
55 | String name = virtualFile.getName().toLowerCase();
56 | return name.equals(flutterName);
57 | }));
58 | return mMainPanel;
59 | }
60 |
61 | @Override
62 | public boolean isModified() {
63 | if (_lastValue == null) {
64 | return false;
65 | }
66 | return !_lastValue.equals(mButton.getText());
67 | }
68 |
69 |
70 | /**
71 | * 点击【apply】、【OK】时,调用
72 | */
73 | @Override
74 | public void apply() {
75 | String newValue = mButton.getText();
76 | PropertiesComponent propertiesComponent = PropertiesComponent.getInstance();
77 | propertiesComponent.setValue(FLUTTER_PATH_KEY, newValue);
78 | }
79 |
80 | /**
81 | * 点击【Reset】时,调用
82 | */
83 | @Override
84 | public void reset() {
85 | // 重置数据
86 | mButton.setText(_lastValue);
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/resources/icons/ic_excavator.svg:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/resources/META-INF/pluginIcon.svg:
--------------------------------------------------------------------------------
1 |
3 | ¬
--------------------------------------------------------------------------------
/src/cn/neday/excavator/tool/ConsoleToolFactory.java:
--------------------------------------------------------------------------------
1 | package cn.neday.excavator.tool;
2 |
3 | import com.intellij.openapi.project.Project;
4 | import com.intellij.openapi.ui.popup.JBPopup;
5 | import com.intellij.openapi.ui.popup.PopupChooserBuilder;
6 | import com.intellij.openapi.wm.ToolWindow;
7 | import com.intellij.openapi.wm.ToolWindowFactory;
8 | import com.intellij.ui.JBColor;
9 | import com.intellij.ui.awt.RelativePoint;
10 | import com.intellij.ui.components.JBList;
11 | import com.intellij.ui.content.Content;
12 | import com.intellij.ui.content.ContentFactory;
13 | import org.jetbrains.annotations.NotNull;
14 |
15 | import javax.swing.*;
16 | import javax.swing.border.Border;
17 | import javax.swing.event.ChangeEvent;
18 | import javax.swing.event.ChangeListener;
19 | import java.awt.*;
20 | import java.awt.event.MouseAdapter;
21 | import java.awt.event.MouseEvent;
22 | import java.awt.event.MouseListener;
23 |
24 | public class ConsoleToolFactory implements ToolWindowFactory {
25 | private JPanel mPanel;
26 | private JScrollPane mScrollPane;
27 | private JTextArea mTxtContent;
28 |
29 | @Override
30 | public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindow toolWindow) {
31 | ContentFactory contentFactory = ContentFactory.SERVICE.getInstance();
32 | Content content = contentFactory.createContent(mPanel, "Logcat", false);
33 | toolWindow.getContentManager().addContent(content);
34 |
35 | // 禁止编辑
36 | mTxtContent.setEditable(false);
37 |
38 | // 去除边框
39 | mTxtContent.setBorder(BorderFactory.createLineBorder(JBColor.BLACK, 0));
40 | mScrollPane.setBorder(BorderFactory.createLineBorder(JBColor.BLACK, 0));
41 | mPanel.setBorder(BorderFactory.createLineBorder(JBColor.BLACK, 0));
42 |
43 | // 设置透明
44 | mPanel.setOpaque(false);
45 | mScrollPane.setOpaque(false);
46 | mScrollPane.getViewport().setOpaque(false);
47 | mTxtContent.setOpaque(false);
48 |
49 | // 鼠标事件
50 | mTxtContent.removeMouseListener(mouseListener);
51 | mTxtContent.addMouseListener(mouseListener);
52 |
53 | // 鼠标事件
54 | mTxtContent.removeMouseListener(mouseAdapter);
55 | mTxtContent.addMouseListener(mouseAdapter);
56 |
57 | // 输入变化事件
58 | mTxtContent.getCaret().removeChangeListener(changeListener);
59 | mTxtContent.getCaret().addChangeListener(changeListener);
60 | }
61 |
62 | /**
63 | * 鼠标进出/入事件
64 | */
65 | private final MouseAdapter mouseAdapter = new MouseAdapter() {
66 | public void mouseEntered(MouseEvent mouseEvent) {
67 | // 鼠标进入Text区后变为文本输入指针
68 | mTxtContent.setCursor(new Cursor(Cursor.TEXT_CURSOR));
69 | }
70 |
71 | public void mouseExited(MouseEvent mouseEvent) {
72 | // 鼠标离开Text区后恢复默认形态
73 | mTxtContent.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
74 | }
75 | };
76 |
77 | /**
78 | * 鼠标改变事件
79 | */
80 | private final ChangeListener changeListener = new ChangeListener() {
81 | public void stateChanged(ChangeEvent e) {
82 | // 使Text区的文本光标显示
83 | mTxtContent.getCaret().setVisible(true);
84 | }
85 | };
86 |
87 | /**
88 | * 鼠标右键事件
89 | */
90 | private final MouseListener mouseListener = new MouseListener() {
91 | @Override
92 | public void mouseClicked(MouseEvent e) {
93 | if (e.getButton() == 3) { // 鼠标右键
94 | // 添加右键菜单的内容
95 | JBList list = new JBList<>();
96 | String[] title = new String[2];
97 | title[0] = " Select All";
98 | title[1] = " Clear All";
99 |
100 | // 设置数据
101 | list.setListData(title);
102 | list.setFocusable(false);
103 |
104 | // 设置边框
105 | Border lineBorder = BorderFactory.createLineBorder(JBColor.BLACK, 1);
106 | list.setBorder(lineBorder);
107 |
108 | // 创建菜单 添加点击项的监听事件
109 | JBPopup popup = new PopupChooserBuilder(list)
110 | .setItemChoosenCallback(() -> {
111 | String value = list.getSelectedValue();
112 | if (value.contains("Clear All")) {
113 | mTxtContent.setText("");
114 | } else if (value.contains("Select All")) {
115 | mTxtContent.selectAll();
116 | }
117 | }).createPopup();
118 |
119 | // 设置大小
120 | Dimension dimension = popup.getContent().getPreferredSize();
121 | popup.setSize(new Dimension(150, dimension.height));
122 |
123 | // 传入e,获取位置进行显示
124 | popup.show(new RelativePoint(e));
125 | list.clearSelection();
126 |
127 | // 添加鼠标进入List事件
128 | list.addMouseListener(new MouseAdapter() {
129 | @Override
130 | public void mouseEntered(MouseEvent e) {
131 | super.mouseEntered(e);
132 | }
133 |
134 | @Override
135 | public void mouseExited(MouseEvent e) {
136 | super.mouseExited(e);
137 | list.clearSelection();
138 | }
139 | });
140 | }
141 | }
142 |
143 | @Override
144 | public void mousePressed(MouseEvent e) {
145 |
146 | }
147 |
148 | @Override
149 | public void mouseReleased(MouseEvent e) {
150 |
151 | }
152 |
153 | @Override
154 | public void mouseEntered(MouseEvent e) {
155 |
156 | }
157 |
158 | @Override
159 | public void mouseExited(MouseEvent e) {
160 |
161 | }
162 | };
163 | }
164 |
--------------------------------------------------------------------------------
/src/cn/neday/excavator/action/kill/BaseKillAction.kt:
--------------------------------------------------------------------------------
1 | package cn.neday.excavator.action.kill
2 |
3 | import cn.neday.excavator.action.BaseAnAction
4 | import cn.neday.excavator.checker.ProjectChecker
5 | import com.intellij.openapi.actionSystem.AnActionEvent
6 | import com.intellij.openapi.actionSystem.PlatformDataKeys
7 | import java.io.BufferedReader
8 | import java.io.IOException
9 | import java.io.InputStreamReader
10 | import java.util.*
11 |
12 |
13 | abstract class BaseKillAction : BaseAnAction() {
14 | abstract val killWhat: String
15 | abstract val processNameOnUnix: String
16 | abstract val processWhereOnUnixOnWindows: String
17 |
18 | override fun update(event: AnActionEvent) {
19 | val project = event.getData(PlatformDataKeys.PROJECT)
20 | val projectPath = project?.basePath
21 | event.presentation.isEnabledAndVisible = ProjectChecker().check(projectPath)
22 | }
23 |
24 | override fun actionPerformed(event: AnActionEvent) {
25 | val pids = try {
26 | pids
27 | } catch (e: UnsupportedOperationException) {
28 | showErrorMessage("Could not get process data!")
29 | return
30 | }
31 | if (pids.isEmpty()) {
32 | showErrorMessage("No $killWhat process is running!")
33 | } else {
34 | var result = true
35 | for (pid in pids) {
36 | result = result and killProcess(pid)
37 | }
38 | if (result) {
39 | showInfo("$killWhat was killed! Your IDE may show you some other dialogs, it's safe to ignore them.")
40 | } else {
41 | showErrorMessage("Could not kill $killWhat! Check that your system supports killing processes!")
42 | }
43 | }
44 | }
45 |
46 | @get:Throws(UnsupportedOperationException::class)
47 | private val pids: Array
48 | get() = if (isWindowsOS()) {
49 | pidsOnWindows
50 | } else {
51 | pidsOnUnix
52 | }
53 |
54 |
55 | /**
56 | * @param pid The PID of the process to kill
57 | * @return true if killed, false if not
58 | */
59 | private fun killProcess(pid: String): Boolean {
60 | return if (isWindowsOS()) {
61 | killProcessOnWindows(pid)
62 | } else {
63 | killProcessOnUnix(pid)
64 | }
65 | }
66 |
67 | @get:Throws(UnsupportedOperationException::class)
68 | private val pidsOnWindows: Array
69 | get() {
70 | val pids = ArrayList()
71 | val r = Runtime.getRuntime()
72 | val p: Process
73 | try {
74 | p = r.exec("wmic process where \"$processWhereOnUnixOnWindows\" get processid")
75 | p.waitFor()
76 | val b = BufferedReader(InputStreamReader(p.inputStream))
77 | var line: String? = null
78 | while (b.readLine()?.also { line = it } != null) {
79 | try {
80 | line?.trim { it <= ' ' }?.toInt()
81 | line?.trim { it <= ' ' }?.let { pids.add(it) }
82 | } catch (e: NumberFormatException) {
83 | //Don't add it, it's a string!
84 | }
85 | }
86 | b.close()
87 | } catch (e: IOException) {
88 | e.printStackTrace()
89 | throw UnsupportedOperationException("wmic parsing failed!")
90 | } catch (e: InterruptedException) {
91 | e.printStackTrace()
92 | throw UnsupportedOperationException("wmic parsing failed!")
93 | }
94 | return pids.toTypedArray()
95 | }
96 |
97 | @get:Throws(UnsupportedOperationException::class)
98 | private val pidsOnUnix: Array
99 | get() {
100 | val pids = ArrayList()
101 | val r = Runtime.getRuntime()
102 | val p: Process
103 | try {
104 | p = r.exec("pgrep -f $processNameOnUnix")
105 | p.waitFor()
106 | if (p.exitValue() != 0 && p.exitValue() != 1) { //OK found, OK not found
107 | throw UnsupportedOperationException("pgrep returned error value!")
108 | } else {
109 | val b = BufferedReader(InputStreamReader(p.inputStream))
110 | var line: String?
111 | while (b.readLine().also { line = it } != null) {
112 | line?.let { pids.add(it) }
113 | }
114 | b.close()
115 | }
116 | } catch (e: IOException) {
117 | e.printStackTrace()
118 | throw UnsupportedOperationException("pgrep parsing failed!")
119 | } catch (e: InterruptedException) {
120 | e.printStackTrace()
121 | throw UnsupportedOperationException("pgrep parsing failed!")
122 | }
123 | return pids.toTypedArray()
124 | }
125 |
126 | private fun killProcessOnWindows(pid: String): Boolean {
127 | val r = Runtime.getRuntime()
128 | val p: Process
129 | return try {
130 | p = r.exec("taskkill /F /PID $pid")
131 | p.waitFor()
132 | true
133 | } catch (e: IOException) {
134 | e.printStackTrace()
135 | false
136 | } catch (e: InterruptedException) {
137 | e.printStackTrace()
138 | false
139 | }
140 | }
141 |
142 | private fun killProcessOnUnix(pid: String): Boolean {
143 | val r = Runtime.getRuntime()
144 | val p: Process
145 | return try {
146 | p = r.exec("kill -9 $pid")
147 | p.waitFor()
148 | p.exitValue() == 0
149 | } catch (e: IOException) {
150 | e.printStackTrace()
151 | false
152 | } catch (e: InterruptedException) {
153 | e.printStackTrace()
154 | false
155 | }
156 | }
157 | }
--------------------------------------------------------------------------------
/resources/META-INF/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 | cn.neday.excavator
3 | Flutter Build Runner Helper
4 | 1.9
5 | nEdAy
6 |
7 |
9 | Flutter Build Runner Helper, to make it easier to execute build_runner commands.
10 | Adds the following build_runner commands to Android Studio:
11 |
12 | - Build : flutter packages pub run build_runner build
13 | - Rebuild : flutter packages pub run build_runner build --delete-conflicting-outputs
14 | - Watch : flutter packages pub run build_runner watch
15 | - Clean : flutter packages pub run build_runner clean
16 |
17 | - Kill Gradle : Kill Gradle if a current task is running
18 | - Kill Flutter : Kill Flutter if a current task is running
19 |
20 |
21 | There are two basic ways to invoke a command:
22 |
23 | - Click the action button in the Toolbar.
24 | - Use the shortcut key.
25 |
26 | ]]>
27 |
28 | 1.9
30 |
31 | - Modify the Project SDK to Android Studio AI-193.6911.18.40.6514223.
32 |
33 | 1.8
34 |
35 | - Modify the Project SDK to IntelliJ IDEA IU-201.8743.12.
36 |
37 | 1.7
38 |
39 | - Add two new Actions: 'Kill Gradle' and 'Kill Flutter'.
40 |
41 | 1.6
42 |
43 | - Only can choose single file,can not choose folder when choose where is flutter path.
44 | - Fixed an exception when the flutter path was set in the preference.(The path was never set before)
45 |
46 | 1.5
47 |
48 | - Only Flutter Project show icons of actions.
49 | - Both output inputStream and errorStream.
50 |
51 | 1.4
52 |
53 | - Optimize UI/Hint.
54 | - The Logcat automatically follows to the bottom of the scroll.
55 |
56 | 1.3
57 |
58 | - Add Setting Configurable.
59 | - Add FileChooserDescriptor.withFileFilter.
60 |
61 | 1.2
62 |
63 | - Add log output to ToolWindow.
64 |
65 | 1.1
66 |
67 | - Update the action icon.
68 | - Add plugin icon.
69 | - Fixed the issue: flutter path not found in Mac OS.
70 |
71 | 1.0
72 |
73 | - Initial release.
74 |
75 | ]]>
76 |
77 |
78 |
79 |
80 |
81 |
83 | com.intellij.modules.platform
84 |
85 |
86 |
88 |
89 |
90 |
91 |
94 |
95 |
96 |
97 |
98 |
99 |
103 |
104 |
105 |
106 |
110 |
111 |
112 |
113 |
116 |
117 |
118 |
119 |
124 |
125 |
126 |
127 |
130 |
131 |
132 |
133 |
136 |
137 |
138 |
139 |
140 |
--------------------------------------------------------------------------------
/src/cn/neday/excavator/action/generation/BaseGenerationAction.kt:
--------------------------------------------------------------------------------
1 | package cn.neday.excavator.action.generation
2 |
3 | import cn.neday.excavator.action.BaseAnAction
4 | import cn.neday.excavator.checker.ProjectChecker
5 | import cn.neday.excavator.setting.Setting.FLUTTER_PATH_KEY
6 | import com.intellij.ide.util.PropertiesComponent
7 | import com.intellij.openapi.actionSystem.AnActionEvent
8 | import com.intellij.openapi.actionSystem.PlatformDataKeys
9 | import com.intellij.openapi.fileChooser.FileChooser
10 | import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
11 | import com.intellij.openapi.progress.PerformInBackgroundOption
12 | import com.intellij.openapi.progress.ProgressIndicator
13 | import com.intellij.openapi.progress.Task
14 | import com.intellij.openapi.project.Project
15 | import com.intellij.openapi.wm.ToolWindow
16 | import com.intellij.openapi.wm.ToolWindowManager
17 | import java.io.BufferedInputStream
18 | import java.io.BufferedReader
19 | import java.io.File
20 | import java.io.InputStreamReader
21 | import javax.swing.JScrollBar
22 | import javax.swing.JScrollPane
23 | import javax.swing.JTextArea
24 |
25 |
26 | abstract class BaseGenerationAnAction : BaseAnAction() {
27 | abstract val cmd: String
28 | abstract val title: String
29 | abstract val successMessage: String
30 | abstract val errorMessage: String
31 |
32 | override fun update(event: AnActionEvent) {
33 | val project = event.getData(PlatformDataKeys.PROJECT)
34 | val projectPath = project?.basePath
35 | event.presentation.isEnabledAndVisible = ProjectChecker().check(projectPath)
36 | }
37 |
38 | override fun actionPerformed(event: AnActionEvent) {
39 | val project = event.getData(PlatformDataKeys.PROJECT)
40 | project?.let {
41 | val propertiesComponent = PropertiesComponent.getInstance()
42 | var flutterPath = propertiesComponent.getValue(FLUTTER_PATH_KEY)
43 | if (flutterPath.isNullOrEmpty()) {
44 | val flutterName = if (isWindowsOS()) "flutter.bat" else "flutter"
45 | showInfo("Flutter path is not defined. Please locate your Flutter installation directory (../../flutter/bin/$flutterName).")
46 | flutterPath = chooseFlutterPath(project, flutterName)
47 | if (flutterPath == CANCEL_SIGNAL) {
48 | return
49 | }
50 | propertiesComponent.setValue(FLUTTER_PATH_KEY, flutterPath)
51 | }
52 | val projectPath = project.basePath
53 | if (!ProjectChecker().check(projectPath)) {
54 | showErrorMessage("Current directory does not seem to be a valid Flutter project directory.")
55 | } else {
56 | projectPath?.let { execCommand(project, flutterPath, it) }
57 | }
58 | } ?: showErrorMessage("Current directory does not seem to be a project directory.")
59 | }
60 |
61 | private fun chooseFlutterPath(project: Project, flutterName: String): String {
62 | val descriptor = FileChooserDescriptorFactory.createSingleFileDescriptor()
63 | .withFileFilter { virtualFile ->
64 | val name = virtualFile.name.toLowerCase()
65 | name == flutterName
66 | }
67 | val selectedFile = FileChooser.chooseFiles(descriptor, project, null)
68 | if (selectedFile.isEmpty()) {
69 | showErrorMessage("You didn't choose any files. Cancel the action.")
70 | return CANCEL_SIGNAL
71 | }
72 | val file = selectedFile[0]
73 | return if (file.name != flutterName) {
74 | showErrorMessage("The file you choose is not flutter. Please choose again.")
75 | chooseFlutterPath(project, flutterName)
76 | } else {
77 | file.path
78 | }
79 | }
80 |
81 | private fun execCommand(project: Project, flutterPath: String, dirPath: String) {
82 | var isBuildRunnerSuccess = false
83 | // 将项目对象,ToolWindow的id传入,获取控件对象
84 | val toolWindow: ToolWindow? = ToolWindowManager.getInstance(project).getToolWindow("Build Runner")
85 | // 无论当前状态为关闭/打开,进行强制打开ToolWindow
86 | toolWindow?.show {}
87 | val jScrollPane = toolWindow?.contentManager?.getContent(0)?.component?.getComponent(0) as? JScrollPane?
88 | val verticalBar: JScrollBar? = jScrollPane?.verticalScrollBar
89 | val jTextArea = jScrollPane?.viewport?.getComponent(0) as? JTextArea?
90 | project.asyncTask(title = title, runAction = {
91 | val fillCmd = "$flutterPath $cmd"
92 | log(jTextArea, verticalBar, "\$ $fillCmd")
93 | val process = Runtime.getRuntime().exec(fillCmd, null, File(dirPath))
94 | val bufferedErrorStream = BufferedInputStream(process.errorStream)
95 | val bufferedInputStream = BufferedInputStream(process.inputStream)
96 | val bufferedErrorReader = BufferedReader(InputStreamReader(bufferedErrorStream, "GBK"))
97 | val bufferedInputReader = BufferedReader(InputStreamReader(bufferedInputStream, "GBK"))
98 | var lineStr: String?
99 | while (bufferedInputReader.readLine().also { lineStr = it } != null) {
100 | log(jTextArea, verticalBar, lineStr)
101 | }
102 | while (bufferedErrorReader.readLine().also { lineStr = it } != null) {
103 | log(jTextArea, verticalBar, lineStr)
104 | }
105 | val exitVal = process.waitFor()
106 | bufferedErrorReader.close()
107 | bufferedInputReader.close()
108 | bufferedErrorStream.close()
109 | bufferedInputStream.close()
110 | isBuildRunnerSuccess = if (exitVal == 0) {
111 | log(jTextArea, verticalBar, "build_runner Success! Exit with code: $exitVal")
112 | true
113 | } else {
114 | log(jTextArea, verticalBar, "build_runner Error! Exit with code: $exitVal")
115 | false
116 | }
117 | }, successAction = {
118 | if (isBuildRunnerSuccess) {
119 | showInfo(successMessage)
120 | } else {
121 | showErrorMessage("An exception error occurred during build_runner execution. Please manually execute and resolve the error before using this plugin.")
122 | }
123 | }, failAction = {
124 | showErrorMessage(errorMessage + ", message:" + it.localizedMessage)
125 | })
126 | }
127 |
128 | private fun log(jTextArea: JTextArea?, verticalBar: JScrollBar?, message: String?) {
129 | if (!message.isNullOrEmpty() && jTextArea != null && verticalBar != null) {
130 | println(message)
131 | jTextArea.append("\n" + message)
132 | verticalBar.value = verticalBar.maximum
133 | }
134 | }
135 |
136 | companion object {
137 |
138 | const val CANCEL_SIGNAL = "CANCEL_SIGNAL"
139 | }
140 | }
141 |
142 | // 创建后台异步任务的Project的扩展函数asyncTask
143 | private fun Project.asyncTask(
144 | title: String,
145 | runAction: (ProgressIndicator) -> Unit,
146 | successAction: (() -> Unit)? = null,
147 | failAction: ((Throwable) -> Unit)? = null,
148 | finishAction: (() -> Unit)? = null
149 | ) {
150 | object : Task.Backgroundable(this, title, true, PerformInBackgroundOption.ALWAYS_BACKGROUND) {
151 | override fun run(p0: ProgressIndicator) {
152 | return runAction.invoke(p0)
153 | }
154 |
155 | override fun onSuccess() {
156 | successAction?.invoke()
157 | }
158 |
159 | override fun onThrowable(error: Throwable) {
160 | failAction?.invoke(error)
161 | }
162 |
163 | override fun onFinished() {
164 | finishAction?.invoke()
165 | }
166 | }.queue()
167 | }
168 |
--------------------------------------------------------------------------------