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]
|
||||
|
||||
### Added
|
||||
|
||||
- Project
|
||||
- Support running file main/tests with hotkey (default: ctrl+shift+f10)
|
||||
|
||||
### Changed
|
||||
|
||||
- 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 theFile = psiFile.virtualFile ?: 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 {
|
||||
|
@ -49,7 +49,7 @@ abstract class ZigConfigProducer<T: ZigExecConfig<T>>: LazyRunConfigurationProdu
|
|||
val psiFile = element.containingFile as? ZigFile ?: return false
|
||||
val theFile = psiFile.virtualFile ?: 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 isConfigurationFromContext(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, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): 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.project.execution.base.ZigConfigProducer
|
||||
import com.falsepattern.zigbrains.project.execution.firstConfigFactory
|
||||
import com.falsepattern.zigbrains.zig.psi.ZigFile
|
||||
import com.intellij.execution.actions.ConfigurationFromContext
|
||||
import com.intellij.execution.configurations.ConfigurationFactory
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
|
@ -36,21 +37,18 @@ class ZigConfigProducerBuild: ZigConfigProducer<ZigExecConfigBuild>() {
|
|||
return firstConfigFactory<ZigConfigTypeBuild>()
|
||||
}
|
||||
|
||||
override fun setupConfigurationFromContext(configuration: ZigExecConfigBuild, element: PsiElement, filePath: Path, theFile: VirtualFile): Boolean {
|
||||
if (LINE_MARKER.elementMatches(element)) {
|
||||
configuration.name = ZigBrainsBundle.message("configuration.build.marker-name")
|
||||
return true
|
||||
}
|
||||
return false
|
||||
override fun setupConfigurationFromContext(configuration: ZigExecConfigBuild, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean {
|
||||
if (theFile.name != "build.zig")
|
||||
return false
|
||||
configuration.name = ZigBrainsBundle.message("configuration.build.marker-name")
|
||||
return true
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean {
|
||||
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.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.configurations.ConfigurationFactory
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.childrenOfType
|
||||
import java.nio.file.Path
|
||||
|
||||
class ZigConfigProducerRun: ZigConfigProducer<ZigExecConfigRun>() {
|
||||
|
@ -35,16 +38,17 @@ class ZigConfigProducerRun: ZigConfigProducer<ZigExecConfigRun>() {
|
|||
return firstConfigFactory<ZigConfigTypeRun>()
|
||||
}
|
||||
|
||||
override fun setupConfigurationFromContext(configuration: ZigExecConfigRun, element: PsiElement, filePath: Path, theFile: VirtualFile): Boolean {
|
||||
if (LINE_MARKER.elementMatches(element)) {
|
||||
configuration.filePath.path = filePath
|
||||
configuration.name = theFile.presentableName
|
||||
return true
|
||||
override fun setupConfigurationFromContext(configuration: ZigExecConfigRun, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean {
|
||||
val members = psiFile.childrenOfType<ZigContainerMembers>().firstOrNull() ?: return false
|
||||
if (members.containerDeclarationList.none { it.decl?.fnProto?.identifier?.textMatches("main") == true }) {
|
||||
return false
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
|
|
|
@ -25,10 +25,13 @@ package com.falsepattern.zigbrains.project.execution.test
|
|||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
||||
import com.falsepattern.zigbrains.project.execution.base.ZigConfigProducer
|
||||
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.configurations.ConfigurationFactory
|
||||
import com.intellij.openapi.vfs.VirtualFile
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.childrenOfType
|
||||
import java.nio.file.Path
|
||||
|
||||
class ZigConfigProducerTest: ZigConfigProducer<ZigExecConfigTest>() {
|
||||
|
@ -36,22 +39,21 @@ class ZigConfigProducerTest: ZigConfigProducer<ZigExecConfigTest>() {
|
|||
return firstConfigFactory<ZigConfigTypeTest>()
|
||||
}
|
||||
|
||||
override fun setupConfigurationFromContext(configuration: ZigExecConfigTest, element: PsiElement, filePath: Path, theFile: VirtualFile): Boolean {
|
||||
if (LINE_MARKER.elementMatches(element)) {
|
||||
configuration.filePath.path = filePath
|
||||
configuration.name = ZigBrainsBundle.message("configuration.test.marker-name", theFile.presentableName)
|
||||
return true
|
||||
override fun setupConfigurationFromContext(configuration: ZigExecConfigTest, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean {
|
||||
val members = psiFile.childrenOfType<ZigContainerMembers>().firstOrNull() ?: return false
|
||||
if (members.containerDeclarationList.none { it.testDecl != null }) {
|
||||
return false
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean {
|
||||
return self.configurationType is ZigConfigTypeTest
|
||||
}
|
||||
}
|
||||
|
||||
private val LINE_MARKER = ZigLineMarkerTest()
|
||||
}
|
|
@ -193,10 +193,14 @@
|
|||
<action
|
||||
id="zigbrains.file.new"
|
||||
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"/>
|
||||
</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>
|
||||
<!-- endregion Project -->
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue