diff --git a/src/main/kotlin/com/github/tempest/framework/console/run/ConsoleCommandLineMarkerProvider.kt b/src/main/kotlin/com/github/tempest/framework/console/run/ConsoleCommandLineMarkerProvider.kt new file mode 100644 index 0000000..525117e --- /dev/null +++ b/src/main/kotlin/com/github/tempest/framework/console/run/ConsoleCommandLineMarkerProvider.kt @@ -0,0 +1,28 @@ +package com.github.tempest.framework.console.run + +import com.github.tempest.framework.TempestBundle +import com.github.tempest.framework.php.getConsoleCommandName +import com.intellij.execution.lineMarker.ExecutorAction +import com.intellij.execution.lineMarker.RunLineMarkerContributor +import com.intellij.icons.AllIcons +import com.intellij.openapi.util.text.StringUtil +import com.intellij.psi.PsiElement +import com.jetbrains.php.lang.psi.elements.Method + +class ConsoleCommandLineMarkerProvider : RunLineMarkerContributor() { + override fun getInfo(element: PsiElement) = when { + element !is Method -> null + else -> { + val commandName = element.getConsoleCommandName() ?: return null + Info( + AllIcons.Actions.Execute, + ExecutorAction.getActions(1), + ) { + TempestBundle.message( + "action.run.target.text", + StringUtil.wrapWithDoubleQuote(TempestBundle.message("action.run.target.command", commandName)), + ) + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/github/tempest/framework/console/run/TempestConsoleCommandRunConfiguration.kt b/src/main/kotlin/com/github/tempest/framework/console/run/TempestConsoleCommandRunConfiguration.kt new file mode 100644 index 0000000..a0bc6da --- /dev/null +++ b/src/main/kotlin/com/github/tempest/framework/console/run/TempestConsoleCommandRunConfiguration.kt @@ -0,0 +1,35 @@ +package com.github.tempest.framework.console.run + +import com.intellij.execution.configurations.ConfigurationFactory +import com.intellij.execution.configurations.RunConfigurationOptions +import com.intellij.openapi.project.Project +import com.jetbrains.php.config.commandLine.PhpCommandSettings +import com.jetbrains.php.run.PhpCommandLineRunConfiguration + +class TempestConsoleCommandRunConfiguration( + project: Project, + factory: ConfigurationFactory, + name: String +) : PhpCommandLineRunConfiguration(project, factory, name) { + override fun fillCommandSettings( + envs: Map, + command: PhpCommandSettings + ) { + val commandName = settings.commandName ?: return + command.setScript("tempest", false) + command.addArgument(commandName) + + command.importCommandLineSettings(settings.commandLineSettings, command.workingDirectory) + command.addEnvs(envs) + } + + override fun getOptions() = super.getOptions() as TempestConsoleCommandRunConfigurationSettings + override fun getOptionsClass(): Class { + return TempestConsoleCommandRunConfigurationSettings::class.java + } + + override fun getConfigurationEditor() = TempestConsoleCommandSettingsEditor(project) + + override fun createSettings() = TempestConsoleCommandRunConfigurationSettings().apply { + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/github/tempest/framework/console/run/TempestConsoleCommandRunConfigurationSettings.kt b/src/main/kotlin/com/github/tempest/framework/console/run/TempestConsoleCommandRunConfigurationSettings.kt new file mode 100644 index 0000000..762bbbf --- /dev/null +++ b/src/main/kotlin/com/github/tempest/framework/console/run/TempestConsoleCommandRunConfigurationSettings.kt @@ -0,0 +1,37 @@ +package com.github.tempest.framework.console.run + +import com.intellij.execution.configurations.LocatableRunConfigurationOptions +import com.jetbrains.php.run.PhpCommandLineSettings +import com.jetbrains.php.run.PhpRunConfigurationSettings + +class TempestConsoleCommandRunConfigurationSettings : PhpRunConfigurationSettings, LocatableRunConfigurationOptions() { + private val myCommandName = string("").provideDelegate(this, "commandName") + private val myBinary = string("./tempest").provideDelegate(this, "binary") + private val myWorkingDirectory = string("").provideDelegate(this, "binary") + + var commandName: String? + get() = myCommandName.getValue(this) + set(scriptName) { + myCommandName.setValue(this, scriptName) + } + + var binary: String? + get() = myBinary.getValue(this) + set(scriptName) { + myBinary.setValue(this, scriptName) + } + + var documentRoot: String? + get() = myBinary.getValue(this) + set(scriptName) { + myBinary.setValue(this, scriptName) + } + + var commandLineSettings = PhpCommandLineSettings() + + override fun getWorkingDirectory() = myWorkingDirectory.getValue(this) + + override fun setWorkingDirectory(p0: String?) { + myWorkingDirectory.setValue(this, p0) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/github/tempest/framework/console/run/TempestConsoleCommandRunConfigurationType.kt b/src/main/kotlin/com/github/tempest/framework/console/run/TempestConsoleCommandRunConfigurationType.kt new file mode 100644 index 0000000..8f49605 --- /dev/null +++ b/src/main/kotlin/com/github/tempest/framework/console/run/TempestConsoleCommandRunConfigurationType.kt @@ -0,0 +1,30 @@ +package com.github.tempest.framework.console.run + +import com.github.tempest.framework.TempestIcons +import com.intellij.execution.configurations.ConfigurationFactory +import com.intellij.execution.configurations.ConfigurationTypeBase +import com.intellij.openapi.project.Project + +class TempestConsoleCommandRunConfigurationType : ConfigurationTypeBase( + ID, + "Tempest Command", + "Runs console command", + TempestIcons.TEMPEST, +) { + init { + addFactory(object : ConfigurationFactory(this) { + override fun getId() = ID + + override fun createTemplateConfiguration(project: Project) = + TempestConsoleCommandRunConfiguration(project, this, "Tempest") + + override fun getOptionsClass() = TempestConsoleCommandRunConfigurationSettings::class.java + }) + } + + companion object { + const val ID = "TempestConsoleCommandRunConfiguration" + + val INSTANCE = TempestConsoleCommandRunConfigurationType() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/github/tempest/framework/console/run/TempestConsoleCommandSettingsEditor.kt b/src/main/kotlin/com/github/tempest/framework/console/run/TempestConsoleCommandSettingsEditor.kt new file mode 100644 index 0000000..fedd6f2 --- /dev/null +++ b/src/main/kotlin/com/github/tempest/framework/console/run/TempestConsoleCommandSettingsEditor.kt @@ -0,0 +1,58 @@ +package com.github.tempest.framework.console.run + +import com.intellij.openapi.options.SettingsEditor +import com.intellij.openapi.ui.DialogPanel +import com.intellij.ui.dsl.builder.Align +import com.intellij.ui.dsl.builder.LabelPosition +import com.intellij.ui.dsl.builder.TopGap +import com.intellij.ui.dsl.builder.panel +import com.jetbrains.php.run.PhpCommandLineConfigurationEditor +import javax.swing.JPanel +import javax.swing.JTextField + +private fun PhpCommandLineConfigurationEditor.getMainPanel(): JPanel? { + val reflection = PhpCommandLineConfigurationEditor::class.java.getDeclaredField("myMainPanel") + reflection.isAccessible = true + return reflection.get(this) as JPanel? +} + +class TempestConsoleCommandSettingsEditor private constructor(): SettingsEditor() { + private val commandNameField = JTextField() + private val phpCommandLineConfigurationEditor = PhpCommandLineConfigurationEditor() + + private lateinit var myPanel: DialogPanel + + constructor(project: com.intellij.openapi.project.Project) : this() { + myPanel = panel { + row { + cell(commandNameField) + .label("Command:", LabelPosition.LEFT) + .align(Align.FILL) + }.topGap(TopGap.MEDIUM) + + row { + phpCommandLineConfigurationEditor.init(project, true) + phpCommandLineConfigurationEditor.getMainPanel()?.apply { + scrollCell(this).align(Align.FILL) + } + }.topGap(TopGap.MEDIUM) + } + } + + override fun resetEditorFrom(tempestConsoleCommandRunConfiguration: TempestConsoleCommandRunConfiguration) { + val settings = tempestConsoleCommandRunConfiguration.settings + + myPanel.reset() + commandNameField.text = settings.commandName + phpCommandLineConfigurationEditor.resetEditorFrom(settings.commandLineSettings) + } + + override fun applyEditorTo(tempestConsoleCommandRunConfiguration: TempestConsoleCommandRunConfiguration) { + val settings = tempestConsoleCommandRunConfiguration.settings + + settings.commandName = commandNameField.text + phpCommandLineConfigurationEditor.applyEditorTo(settings.commandLineSettings) + } + + override fun createEditor() = myPanel +} \ No newline at end of file diff --git a/src/main/kotlin/com/github/tempest/framework/console/run/TempestRunAnythingProvider.kt b/src/main/kotlin/com/github/tempest/framework/console/run/TempestRunAnythingProvider.kt new file mode 100644 index 0000000..9245ab7 --- /dev/null +++ b/src/main/kotlin/com/github/tempest/framework/console/run/TempestRunAnythingProvider.kt @@ -0,0 +1,38 @@ +package com.github.tempest.framework.console.run + +import com.github.tempest.framework.TempestBundle +import com.github.tempest.framework.TempestIcons +import com.github.tempest.framework.console.index.ConsoleCommandsIndex +import com.intellij.icons.AllIcons +import com.intellij.ide.actions.runAnything.activity.RunAnythingAnActionProvider +import com.intellij.openapi.actionSystem.CommonDataKeys +import com.intellij.openapi.actionSystem.DataContext +import com.intellij.openapi.application.ReadAction +import com.intellij.util.indexing.FileBasedIndex + +class TempestRunAnythingProvider : RunAnythingAnActionProvider() { + override fun getCommand(value: TempestRunCommandAction) = + TempestBundle.message("action.run.target.command", value.commandName) + + override fun getHelpCommandPlaceholder() = "tempest " + + override fun getCompletionGroupTitle() = "Tempest" + + override fun getHelpCommand() = "tempest" + + override fun getHelpGroupTitle() = "PHP" + + override fun getHelpIcon() = TempestIcons.TEMPEST + + override fun getIcon(value: TempestRunCommandAction) = AllIcons.Actions.Execute + + override fun getValues(dataContext: DataContext, pattern: String): Collection { + val project = CommonDataKeys.PROJECT.getData(dataContext) ?: return emptyList() + + return ReadAction.compute, Throwable> { + FileBasedIndex.getInstance() + .getAllKeys(ConsoleCommandsIndex.key, project) + .map { TempestRunCommandAction(it) } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/github/tempest/framework/console/run/TempestRunCommandAction.kt b/src/main/kotlin/com/github/tempest/framework/console/run/TempestRunCommandAction.kt new file mode 100644 index 0000000..a63c875 --- /dev/null +++ b/src/main/kotlin/com/github/tempest/framework/console/run/TempestRunCommandAction.kt @@ -0,0 +1,37 @@ +package com.github.tempest.framework.console.run + +import com.github.tempest.framework.TempestBundle +import com.intellij.execution.Executor +import com.intellij.execution.RunManagerEx +import com.intellij.execution.runners.ExecutionUtil +import com.intellij.icons.AllIcons +import com.intellij.openapi.actionSystem.AnAction +import com.intellij.openapi.actionSystem.AnActionEvent + +class TempestRunCommandAction(val commandName: String) : AnAction() { + init { + templatePresentation.setText(TempestBundle.message("action.run.target.text", commandName), false) + templatePresentation.description = TempestBundle.message("action.run.target.description", commandName) + templatePresentation.icon = AllIcons.Actions.Execute + } + + override fun actionPerformed(event: AnActionEvent) { + val project = event.project ?: return + + val runManager = RunManagerEx.getInstanceEx(project) + val producer = TempestRunConfigurationProducer() + val configurationFactory = producer.configurationFactory + + val runConfiguration = TempestConsoleCommandRunConfiguration( + project, + configurationFactory, + TempestBundle.message("action.run.target.command", commandName), + ) + .apply { settings.commandName = commandName } + + val configuration = runManager.createConfiguration(runConfiguration, configurationFactory) + + runManager.setTemporaryConfiguration(configuration) + ExecutionUtil.runConfiguration(configuration, Executor.EXECUTOR_EXTENSION_NAME.extensionList.first()) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/github/tempest/framework/console/run/TempestRunConfigurationFactory.kt b/src/main/kotlin/com/github/tempest/framework/console/run/TempestRunConfigurationFactory.kt new file mode 100644 index 0000000..47b643f --- /dev/null +++ b/src/main/kotlin/com/github/tempest/framework/console/run/TempestRunConfigurationFactory.kt @@ -0,0 +1,13 @@ +package com.github.tempest.framework.console.run + +import com.intellij.execution.configurations.ConfigurationFactory +import com.intellij.openapi.project.Project + +class TempestRunConfigurationFactory(private val runConfigurationType: TempestConsoleCommandRunConfigurationType) : + ConfigurationFactory(runConfigurationType) { + override fun getId() = TempestConsoleCommandRunConfigurationType.ID + override fun getName() = runConfigurationType.displayName + + override fun createTemplateConfiguration(project: Project) = + TempestConsoleCommandRunConfiguration(project, this, "name") +} \ No newline at end of file diff --git a/src/main/kotlin/com/github/tempest/framework/console/run/TempestRunConfigurationProducer.kt b/src/main/kotlin/com/github/tempest/framework/console/run/TempestRunConfigurationProducer.kt new file mode 100644 index 0000000..73a6442 --- /dev/null +++ b/src/main/kotlin/com/github/tempest/framework/console/run/TempestRunConfigurationProducer.kt @@ -0,0 +1,37 @@ +package com.github.tempest.framework.console.run + +import com.github.tempest.framework.TempestBundle +import com.github.tempest.framework.php.getConsoleCommandName +import com.intellij.execution.actions.ConfigurationContext +import com.intellij.execution.actions.LazyRunConfigurationProducer +import com.intellij.openapi.util.Ref +import com.intellij.psi.PsiElement +import com.jetbrains.php.lang.psi.elements.Method + +class TempestRunConfigurationProducer : LazyRunConfigurationProducer() { + override fun setupConfigurationFromContext( + configuration: TempestConsoleCommandRunConfiguration, + context: ConfigurationContext, + sourceElement: Ref + ): Boolean { + val element = context.psiLocation as? Method ?: return false + val commandName = element.getConsoleCommandName() ?: return false + + configuration.settings.commandName = commandName + configuration.name = TempestBundle.message("action.run.target.command", commandName) + + return true + } + + override fun isConfigurationFromContext( + configuration: TempestConsoleCommandRunConfiguration, + context: ConfigurationContext + ): Boolean { + val method = context.psiLocation as? Method ?: return false + + return configuration.settings.commandName == method.getConsoleCommandName() + } + + override fun getConfigurationFactory() = + TempestRunConfigurationFactory(TempestConsoleCommandRunConfigurationType.INSTANCE) +} diff --git a/src/main/kotlin/com/github/tempest/framework/php/mixin.kt b/src/main/kotlin/com/github/tempest/framework/php/mixin.kt index 275ea71..e6b0da4 100644 --- a/src/main/kotlin/com/github/tempest/framework/php/mixin.kt +++ b/src/main/kotlin/com/github/tempest/framework/php/mixin.kt @@ -1,7 +1,10 @@ package com.github.tempest.framework.php +import com.github.tempest.framework.TempestFrameworkClasses +import com.intellij.openapi.util.text.StringUtil import com.intellij.psi.util.PsiTreeUtil import com.jetbrains.php.lang.psi.PhpFile +import com.jetbrains.php.lang.psi.elements.Method import com.jetbrains.php.lang.psi.elements.Variable fun PhpFile.getPhpViewVariables(): Set { @@ -11,3 +14,14 @@ fun PhpFile.getPhpViewVariables(): Set { .distinctBy { it.name } .toSet() } + +fun Method.getConsoleCommandName(): String? { + return this + .getAttributes(TempestFrameworkClasses.ConsoleCommand) + .firstOrNull() + ?.arguments + ?.run { this.find { it.name == "name" } ?: firstOrNull() } + ?.argument + ?.value + ?.run { StringUtil.unquoteString(this) } +} \ No newline at end of file diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index 401a071..ece6bf4 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -10,6 +10,15 @@ messages.TempestBundle + + + + - diff --git a/src/main/resources/messages/TempestBundle.properties b/src/main/resources/messages/TempestBundle.properties index e69de29..1437e05 100644 --- a/src/main/resources/messages/TempestBundle.properties +++ b/src/main/resources/messages/TempestBundle.properties @@ -0,0 +1,3 @@ +action.run.target.text=Run {0} +action.run.target.description=Tempest console command +action.run.target.command=tempest {0}