feat: Add support for ctrl+shift+f10
This commit is contained in:
parent
cc062b533e
commit
af9ebee500
7 changed files with 136 additions and 33 deletions
|
@ -17,6 +17,11 @@ Changelog structure reference:
|
||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Project
|
||||||
|
- Support running file main/tests with hotkey (default: ctrl+shift+f10)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- Direnv
|
- Direnv
|
||||||
|
|
|
@ -0,0 +1,90 @@
|
||||||
|
/*
|
||||||
|
* This file is part of ZigBrains.
|
||||||
|
*
|
||||||
|
* Copyright (C) 2023-2025 FalsePattern
|
||||||
|
* All Rights Reserved
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included
|
||||||
|
* in all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* ZigBrains is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Lesser General Public License as published by
|
||||||
|
* the Free Software Foundation, only version 3 of the License.
|
||||||
|
*
|
||||||
|
* ZigBrains is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public License
|
||||||
|
* along with ZigBrains. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.falsepattern.zigbrains.project.actions
|
||||||
|
|
||||||
|
import com.falsepattern.zigbrains.project.execution.base.ZigExecConfig
|
||||||
|
import com.falsepattern.zigbrains.project.execution.run.ZigConfigProducerRun
|
||||||
|
import com.falsepattern.zigbrains.project.execution.run.ZigExecConfigRun
|
||||||
|
import com.falsepattern.zigbrains.project.execution.test.ZigConfigProducerTest
|
||||||
|
import com.falsepattern.zigbrains.project.execution.test.ZigExecConfigTest
|
||||||
|
import com.intellij.execution.ExecutionManager
|
||||||
|
import com.intellij.execution.actions.ConfigurationContext
|
||||||
|
import com.intellij.execution.actions.RunConfigurationProducer
|
||||||
|
import com.intellij.execution.executors.DefaultRunExecutor
|
||||||
|
import com.intellij.execution.runners.ExecutionEnvironmentBuilder
|
||||||
|
import com.intellij.openapi.actionSystem.ActionUpdateThread
|
||||||
|
import com.intellij.openapi.actionSystem.AnActionEvent
|
||||||
|
import com.intellij.openapi.actionSystem.CommonDataKeys
|
||||||
|
import com.intellij.openapi.project.DumbAwareAction
|
||||||
|
|
||||||
|
class ZigRunFileAction: DumbAwareAction() {
|
||||||
|
override fun actionPerformed(e: AnActionEvent) {
|
||||||
|
val file = e.getData(CommonDataKeys.PSI_FILE) ?: return
|
||||||
|
val config = getConfig(e) ?: return
|
||||||
|
val project = file.project
|
||||||
|
val builder = ExecutionEnvironmentBuilder.createOrNull(DefaultRunExecutor.getRunExecutorInstance(), config) ?: return
|
||||||
|
ExecutionManager.getInstance(project).restartRunProfile(builder.build())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getConfig(e: AnActionEvent): ZigExecConfig<*>? {
|
||||||
|
val context = ConfigurationContext.getFromContext(e.dataContext, e.place)
|
||||||
|
return getRunConfiguration(context) ?: getTestConfiguration(context)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun update(e: AnActionEvent) {
|
||||||
|
e.presentation.isEnabledAndVisible = getConfig(e) != null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getRunConfiguration(context: ConfigurationContext): ZigExecConfigRun? {
|
||||||
|
try {
|
||||||
|
val configProducer = RunConfigurationProducer.getInstance(ZigConfigProducerRun::class.java)
|
||||||
|
val settings = configProducer.findExistingConfiguration(context)
|
||||||
|
if (settings != null) {
|
||||||
|
return settings.configuration as? ZigExecConfigRun
|
||||||
|
}
|
||||||
|
val fromContext = configProducer.createConfigurationFromContext(context)
|
||||||
|
if (fromContext != null) {
|
||||||
|
return fromContext.configuration as? ZigExecConfigRun
|
||||||
|
}
|
||||||
|
} catch (_: NullPointerException) {}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
private fun getTestConfiguration(context: ConfigurationContext): ZigExecConfigTest? {
|
||||||
|
try {
|
||||||
|
val configProducer = RunConfigurationProducer.getInstance(ZigConfigProducerTest::class.java)
|
||||||
|
val settings = configProducer.findExistingConfiguration(context)
|
||||||
|
if (settings != null) {
|
||||||
|
return settings.configuration as? ZigExecConfigTest
|
||||||
|
}
|
||||||
|
val fromContext = configProducer.createConfigurationFromContext(context)
|
||||||
|
if (fromContext != null) {
|
||||||
|
return fromContext.configuration as? ZigExecConfigTest
|
||||||
|
}
|
||||||
|
} catch (_: NullPointerException) {}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getActionUpdateThread(): ActionUpdateThread {
|
||||||
|
return ActionUpdateThread.BGT
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,7 +41,7 @@ abstract class ZigConfigProducer<T: ZigExecConfig<T>>: LazyRunConfigurationProdu
|
||||||
val psiFile = element.containingFile as? ZigFile ?: return false
|
val psiFile = element.containingFile as? ZigFile ?: return false
|
||||||
val theFile = psiFile.virtualFile ?: return false
|
val theFile = psiFile.virtualFile ?: return false
|
||||||
val filePath = theFile.toNioPathOrNull() ?: return false
|
val filePath = theFile.toNioPathOrNull() ?: return false
|
||||||
return setupConfigurationFromContext(configuration, element, filePath, theFile)
|
return setupConfigurationFromContext(configuration, element, psiFile, filePath, theFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isConfigurationFromContext(configuration: T, context: ConfigurationContext): Boolean {
|
override fun isConfigurationFromContext(configuration: T, context: ConfigurationContext): Boolean {
|
||||||
|
@ -49,7 +49,7 @@ abstract class ZigConfigProducer<T: ZigExecConfig<T>>: LazyRunConfigurationProdu
|
||||||
val psiFile = element.containingFile as? ZigFile ?: return false
|
val psiFile = element.containingFile as? ZigFile ?: return false
|
||||||
val theFile = psiFile.virtualFile ?: return false
|
val theFile = psiFile.virtualFile ?: return false
|
||||||
val filePath = theFile.toNioPathOrNull() ?: return false
|
val filePath = theFile.toNioPathOrNull() ?: return false
|
||||||
return isConfigurationFromContext(configuration, element, filePath, theFile)
|
return isConfigurationFromContext(configuration, element, psiFile, filePath, theFile)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -78,7 +78,7 @@ abstract class ZigConfigProducer<T: ZigExecConfig<T>>: LazyRunConfigurationProdu
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
protected abstract fun setupConfigurationFromContext(configuration: T, element: PsiElement, filePath: Path, theFile: VirtualFile): Boolean
|
protected abstract fun setupConfigurationFromContext(configuration: T, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean
|
||||||
protected abstract fun isConfigurationFromContext(configuration: T, element: PsiElement, filePath: Path, theFile: VirtualFile): Boolean
|
protected abstract fun isConfigurationFromContext(configuration: T, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean
|
||||||
abstract override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean
|
abstract override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean
|
||||||
}
|
}
|
|
@ -25,6 +25,7 @@ package com.falsepattern.zigbrains.project.execution.build
|
||||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
import com.falsepattern.zigbrains.ZigBrainsBundle
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigConfigProducer
|
import com.falsepattern.zigbrains.project.execution.base.ZigConfigProducer
|
||||||
import com.falsepattern.zigbrains.project.execution.firstConfigFactory
|
import com.falsepattern.zigbrains.project.execution.firstConfigFactory
|
||||||
|
import com.falsepattern.zigbrains.zig.psi.ZigFile
|
||||||
import com.intellij.execution.actions.ConfigurationFromContext
|
import com.intellij.execution.actions.ConfigurationFromContext
|
||||||
import com.intellij.execution.configurations.ConfigurationFactory
|
import com.intellij.execution.configurations.ConfigurationFactory
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
|
@ -36,21 +37,18 @@ class ZigConfigProducerBuild: ZigConfigProducer<ZigExecConfigBuild>() {
|
||||||
return firstConfigFactory<ZigConfigTypeBuild>()
|
return firstConfigFactory<ZigConfigTypeBuild>()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setupConfigurationFromContext(configuration: ZigExecConfigBuild, element: PsiElement, filePath: Path, theFile: VirtualFile): Boolean {
|
override fun setupConfigurationFromContext(configuration: ZigExecConfigBuild, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean {
|
||||||
if (LINE_MARKER.elementMatches(element)) {
|
if (theFile.name != "build.zig")
|
||||||
configuration.name = ZigBrainsBundle.message("configuration.build.marker-name")
|
return false
|
||||||
return true
|
configuration.name = ZigBrainsBundle.message("configuration.build.marker-name")
|
||||||
}
|
return true
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isConfigurationFromContext(configuration: ZigExecConfigBuild, element: PsiElement, filePath: Path, theFile: VirtualFile): Boolean {
|
override fun isConfigurationFromContext(configuration: ZigExecConfigBuild, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean {
|
||||||
return filePath.parent == (configuration.workingDirectory.path ?: return false)
|
return filePath.parent == (configuration.workingDirectory.path ?: return false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean {
|
override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean {
|
||||||
return self.configurationType is ZigConfigTypeBuild
|
return self.configurationType is ZigConfigTypeBuild
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val LINE_MARKER = ZigLineMarkerBuild()
|
|
|
@ -24,10 +24,13 @@ package com.falsepattern.zigbrains.project.execution.run
|
||||||
|
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigConfigProducer
|
import com.falsepattern.zigbrains.project.execution.base.ZigConfigProducer
|
||||||
import com.falsepattern.zigbrains.project.execution.firstConfigFactory
|
import com.falsepattern.zigbrains.project.execution.firstConfigFactory
|
||||||
|
import com.falsepattern.zigbrains.zig.psi.ZigContainerMembers
|
||||||
|
import com.falsepattern.zigbrains.zig.psi.ZigFile
|
||||||
import com.intellij.execution.actions.ConfigurationFromContext
|
import com.intellij.execution.actions.ConfigurationFromContext
|
||||||
import com.intellij.execution.configurations.ConfigurationFactory
|
import com.intellij.execution.configurations.ConfigurationFactory
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.util.childrenOfType
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
class ZigConfigProducerRun: ZigConfigProducer<ZigExecConfigRun>() {
|
class ZigConfigProducerRun: ZigConfigProducer<ZigExecConfigRun>() {
|
||||||
|
@ -35,16 +38,17 @@ class ZigConfigProducerRun: ZigConfigProducer<ZigExecConfigRun>() {
|
||||||
return firstConfigFactory<ZigConfigTypeRun>()
|
return firstConfigFactory<ZigConfigTypeRun>()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setupConfigurationFromContext(configuration: ZigExecConfigRun, element: PsiElement, filePath: Path, theFile: VirtualFile): Boolean {
|
override fun setupConfigurationFromContext(configuration: ZigExecConfigRun, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean {
|
||||||
if (LINE_MARKER.elementMatches(element)) {
|
val members = psiFile.childrenOfType<ZigContainerMembers>().firstOrNull() ?: return false
|
||||||
configuration.filePath.path = filePath
|
if (members.containerDeclarationList.none { it.decl?.fnProto?.identifier?.textMatches("main") == true }) {
|
||||||
configuration.name = theFile.presentableName
|
return false
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
return false
|
configuration.filePath.path = filePath
|
||||||
|
configuration.name = theFile.presentableName
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isConfigurationFromContext(configuration: ZigExecConfigRun, element: PsiElement, filePath: Path, theFile: VirtualFile): Boolean {
|
override fun isConfigurationFromContext(configuration: ZigExecConfigRun, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean {
|
||||||
return filePath == configuration.filePath.path
|
return filePath == configuration.filePath.path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,13 @@ package com.falsepattern.zigbrains.project.execution.test
|
||||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
import com.falsepattern.zigbrains.ZigBrainsBundle
|
||||||
import com.falsepattern.zigbrains.project.execution.base.ZigConfigProducer
|
import com.falsepattern.zigbrains.project.execution.base.ZigConfigProducer
|
||||||
import com.falsepattern.zigbrains.project.execution.firstConfigFactory
|
import com.falsepattern.zigbrains.project.execution.firstConfigFactory
|
||||||
|
import com.falsepattern.zigbrains.zig.psi.ZigContainerMembers
|
||||||
|
import com.falsepattern.zigbrains.zig.psi.ZigFile
|
||||||
import com.intellij.execution.actions.ConfigurationFromContext
|
import com.intellij.execution.actions.ConfigurationFromContext
|
||||||
import com.intellij.execution.configurations.ConfigurationFactory
|
import com.intellij.execution.configurations.ConfigurationFactory
|
||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.util.childrenOfType
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
class ZigConfigProducerTest: ZigConfigProducer<ZigExecConfigTest>() {
|
class ZigConfigProducerTest: ZigConfigProducer<ZigExecConfigTest>() {
|
||||||
|
@ -36,22 +39,21 @@ class ZigConfigProducerTest: ZigConfigProducer<ZigExecConfigTest>() {
|
||||||
return firstConfigFactory<ZigConfigTypeTest>()
|
return firstConfigFactory<ZigConfigTypeTest>()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun setupConfigurationFromContext(configuration: ZigExecConfigTest, element: PsiElement, filePath: Path, theFile: VirtualFile): Boolean {
|
override fun setupConfigurationFromContext(configuration: ZigExecConfigTest, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean {
|
||||||
if (LINE_MARKER.elementMatches(element)) {
|
val members = psiFile.childrenOfType<ZigContainerMembers>().firstOrNull() ?: return false
|
||||||
configuration.filePath.path = filePath
|
if (members.containerDeclarationList.none { it.testDecl != null }) {
|
||||||
configuration.name = ZigBrainsBundle.message("configuration.test.marker-name", theFile.presentableName)
|
return false
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
return false
|
configuration.filePath.path = filePath
|
||||||
|
configuration.name = ZigBrainsBundle.message("configuration.test.marker-name", theFile.presentableName)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun isConfigurationFromContext(configuration: ZigExecConfigTest, element: PsiElement, filePath: Path, theFile: VirtualFile): Boolean {
|
override fun isConfigurationFromContext(configuration: ZigExecConfigTest, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean {
|
||||||
return filePath == configuration.filePath.path
|
return filePath == configuration.filePath.path
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean {
|
override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean {
|
||||||
return self.configurationType is ZigConfigTypeTest
|
return self.configurationType is ZigConfigTypeTest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val LINE_MARKER = ZigLineMarkerTest()
|
|
|
@ -193,10 +193,14 @@
|
||||||
<action
|
<action
|
||||||
id="zigbrains.file.new"
|
id="zigbrains.file.new"
|
||||||
class="com.falsepattern.zigbrains.project.actions.ZigNewFileAction"
|
class="com.falsepattern.zigbrains.project.actions.ZigNewFileAction"
|
||||||
icon="com.falsepattern.zigbrains.Icons.Zig"
|
icon="com.falsepattern.zigbrains.Icons.Zig">
|
||||||
>
|
|
||||||
<add-to-group group-id="NewGroup" anchor="after" relative-to-action="FileTemplateSeparatorGroup"/>
|
<add-to-group group-id="NewGroup" anchor="after" relative-to-action="FileTemplateSeparatorGroup"/>
|
||||||
</action>
|
</action>
|
||||||
|
<!--suppress PluginXmlValidity -->
|
||||||
|
<action id="zigbrains.file.run"
|
||||||
|
class="com.falsepattern.zigbrains.project.actions.ZigRunFileAction"
|
||||||
|
icon="AllIcons.RunConfigurations.TestState.Run"
|
||||||
|
use-shortcut-of="RunClass"/>
|
||||||
</actions>
|
</actions>
|
||||||
<!-- endregion Project -->
|
<!-- endregion Project -->
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue