├── .gitignore ├── LICENSE ├── README.md ├── README_CN.md ├── 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 ├── META-INF │ ├── plugin.xml │ └── pluginIcon.svg └── icons │ ├── ic_build.svg │ ├── ic_clean.svg │ ├── ic_excavator.svg │ ├── ic_kill_flutter.svg │ ├── ic_kill_gradle.svg │ ├── ic_rebuild.svg │ └── ic_watch.svg └── src └── cn └── neday └── excavator ├── action ├── BaseAction.kt ├── generation │ ├── BaseGenerationAction.kt │ ├── BuildAction.kt │ ├── CleanAction.kt │ ├── RebuildAction.kt │ └── WatchAction.kt └── kill │ ├── BaseKillAction.kt │ ├── KillFlutterAction.kt │ └── KillGradleAction.kt ├── checker ├── ICheck.kt └── ProjectChecker.kt ├── service ├── WatchService.kt └── WatchServiceImpl.kt ├── setting ├── Setting.form └── Setting.java └── tool ├── ConsoleToolFactory.form └── ConsoleToolFactory.java /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | /out 3 | /*.iml 4 | /*.jar 5 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | [![License](https://img.shields.io/badge/license-MIT-blue.svg)](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 | -------------------------------------------------------------------------------- /README_CN.md: -------------------------------------------------------------------------------- 1 | # [Flutter-Build-Runner-Helper](https://plugins.jetbrains.com/plugin/14442-flutter-build-runner-helper) 2 | 3 | [![License](https://img.shields.io/badge/license-MIT-blue.svg)](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. -------------------------------------------------------------------------------- /release/build-runner-helper_1.0.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/7b9c0bd8b18b32764ff82bc1967bcdbebfcf383d/release/build-runner-helper_1.0.jar -------------------------------------------------------------------------------- /release/build-runner-helper_1.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/7b9c0bd8b18b32764ff82bc1967bcdbebfcf383d/release/build-runner-helper_1.1.jar -------------------------------------------------------------------------------- /release/build-runner-helper_1.2.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/7b9c0bd8b18b32764ff82bc1967bcdbebfcf383d/release/build-runner-helper_1.2.jar -------------------------------------------------------------------------------- /release/build-runner-helper_1.3.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/7b9c0bd8b18b32764ff82bc1967bcdbebfcf383d/release/build-runner-helper_1.3.jar -------------------------------------------------------------------------------- /release/build-runner-helper_1.4.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/7b9c0bd8b18b32764ff82bc1967bcdbebfcf383d/release/build-runner-helper_1.4.jar -------------------------------------------------------------------------------- /release/build-runner-helper_1.5.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/7b9c0bd8b18b32764ff82bc1967bcdbebfcf383d/release/build-runner-helper_1.5.jar -------------------------------------------------------------------------------- /release/build-runner-helper_1.6.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/7b9c0bd8b18b32764ff82bc1967bcdbebfcf383d/release/build-runner-helper_1.6.jar -------------------------------------------------------------------------------- /release/build-runner-helper_1.7.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/7b9c0bd8b18b32764ff82bc1967bcdbebfcf383d/release/build-runner-helper_1.7.jar -------------------------------------------------------------------------------- /release/build-runner-helper_1.8.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/7b9c0bd8b18b32764ff82bc1967bcdbebfcf383d/release/build-runner-helper_1.8.jar -------------------------------------------------------------------------------- /release/build-runner-helper_1.9.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nEdAy/Flutter-Build-Runner-Helper/7b9c0bd8b18b32764ff82bc1967bcdbebfcf383d/release/build-runner-helper_1.9.jar -------------------------------------------------------------------------------- /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 | 20 |
21 | There are two basic ways to invoke a command: 22 | 26 | ]]>
27 | 28 | 1.9 30 | 33 | 1.8 34 | 37 | 1.7 38 | 41 | 1.6 42 | 46 | 1.5 47 | 51 | 1.4 52 | 56 | 1.3 57 | 61 | 1.2 62 | 65 | 1.1 66 | 71 | 1.0 72 | 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 |
-------------------------------------------------------------------------------- /resources/META-INF/pluginIcon.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | 7 | 8 | 10 | 12 | 14 | ¬ -------------------------------------------------------------------------------- /resources/icons/ic_build.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | 7 | 8 | 10 | -------------------------------------------------------------------------------- /resources/icons/ic_clean.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | 7 | 8 | 10 | -------------------------------------------------------------------------------- /resources/icons/ic_excavator.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | 7 | 8 | 10 | 12 | 14 | -------------------------------------------------------------------------------- /resources/icons/ic_kill_flutter.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | 7 | 8 | 10 | -------------------------------------------------------------------------------- /resources/icons/ic_kill_gradle.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | 7 | 8 | 10 | -------------------------------------------------------------------------------- /resources/icons/ic_rebuild.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | 7 | 8 | 10 | -------------------------------------------------------------------------------- /resources/icons/ic_watch.svg: -------------------------------------------------------------------------------- 1 | 3 | 5 | 6 | 7 | 8 | 10 | -------------------------------------------------------------------------------- /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/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 | -------------------------------------------------------------------------------- /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/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 | } -------------------------------------------------------------------------------- /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/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 | } -------------------------------------------------------------------------------- /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/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/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 | } -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /src/cn/neday/excavator/setting/Setting.form: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /src/cn/neday/excavator/tool/ConsoleToolFactory.form: -------------------------------------------------------------------------------- 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 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------