diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c4c0d34..9a8f3ed9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,11 @@ Changelog structure reference: ## [Unreleased] +### Changed + +- Direnv + - Centralized all direnv toggling into a single project-level option + ## [23.0.2] ### Fixed diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/project/execution/base/Configuration.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/project/execution/base/Configuration.kt index b716b7ca..c7bb73e4 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/project/execution/base/Configuration.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/project/execution/base/Configuration.kt @@ -280,12 +280,6 @@ class ColoredConfigurable(serializedName: String): CheckboxConfigurable(serializ } } -class DirenvConfigurable(serializedName: String, project: Project): CheckboxConfigurable(serializedName, ZigBrainsBundle.message("exec.option.label.direnv"), project.zigProjectSettings.state.direnv) { - override fun clone(): DirenvConfigurable { - return super.clone() as DirenvConfigurable - } -} - class OptimizationConfigurable( @Transient private val serializedName: String, var level: OptimizationLevel = OptimizationLevel.Debug, diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/project/execution/base/ZigExecConfig.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/project/execution/base/ZigExecConfig.kt index ab1ab23b..b03b16ad 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/project/execution/base/ZigExecConfig.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/project/execution/base/ZigExecConfig.kt @@ -24,6 +24,7 @@ package com.falsepattern.zigbrains.project.execution.base import com.falsepattern.zigbrains.ZigBrainsBundle import com.falsepattern.zigbrains.direnv.DirenvCmd +import com.falsepattern.zigbrains.project.settings.zigProjectSettings import com.intellij.execution.ExecutionException import com.intellij.execution.Executor import com.intellij.execution.configurations.ConfigurationFactory @@ -44,8 +45,6 @@ abstract class ZigExecConfig>(project: Project, factory: Con private set var pty = CheckboxConfigurable("pty", ZigBrainsBundle.message("exec.option.label.emulate-terminal"), false) private set - var direnv = DirenvConfigurable("direnv", project) - private set abstract val suggestedName: @ActionText String @Throws(ExecutionException::class) @@ -68,7 +67,7 @@ abstract class ZigExecConfig>(project: Project, factory: Con suspend fun patchCommandLine(commandLine: GeneralCommandLine): GeneralCommandLine { - if (direnv.value) { + if (project.zigProjectSettings.state.direnv) { commandLine.withEnvironment(DirenvCmd.importDirenv(project).env) } return commandLine @@ -82,10 +81,9 @@ abstract class ZigExecConfig>(project: Project, factory: Con val myClone = super.clone() as ZigExecConfig<*> myClone.workingDirectory = workingDirectory.clone() myClone.pty = pty.clone() - myClone.direnv = direnv.clone() @Suppress("UNCHECKED_CAST") return myClone as T } - open fun getConfigurables(): List> = listOf(workingDirectory, pty, direnv) + open fun getConfigurables(): List> = listOf(workingDirectory, pty) } \ No newline at end of file diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/project/newproject/ZigNewProjectPanel.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/project/newproject/ZigNewProjectPanel.kt index 6418285b..ac1abd24 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/project/newproject/ZigNewProjectPanel.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/project/newproject/ZigNewProjectPanel.kt @@ -39,9 +39,9 @@ import com.intellij.util.ui.JBUI import javax.swing.JList import javax.swing.ListSelectionModel -class ZigNewProjectPanel(private var handleGit: Boolean): Disposable { +class ZigNewProjectPanel(private var handleGit: Boolean): Disposable, ZigProjectConfigurationProvider.SettingsPanelHolder { private val git = JBCheckBox() - private val panels = ZigProjectConfigurationProvider.createNewProjectSettingsPanels().onEach { Disposer.register(this, it) } + override val panels = ZigProjectConfigurationProvider.createNewProjectSettingsPanels(this).onEach { Disposer.register(this, it) } private val templateList = JBList(JBList.createDefaultListModel(defaultTemplates)).apply { selectionMode = ListSelectionModel.SINGLE_SELECTION selectedIndex = 0 diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigCoreProjectConfigurationProvider.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigCoreProjectConfigurationProvider.kt index d8a76a88..207da863 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigCoreProjectConfigurationProvider.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigCoreProjectConfigurationProvider.kt @@ -34,8 +34,8 @@ class ZigCoreProjectConfigurationProvider: ZigProjectConfigurationProvider { return ZigProjectConfigurable(project) } - override fun createNewProjectSettingsPanel(): ZigProjectConfigurationProvider.SettingsPanel { - return ZigProjectSettingsPanel(ProjectManager.getInstance().defaultProject) + override fun createNewProjectSettingsPanel(holder: ZigProjectConfigurationProvider.SettingsPanelHolder): ZigProjectConfigurationProvider.SettingsPanel { + return ZigProjectSettingsPanel(holder, ProjectManager.getInstance().defaultProject) } override val priority: Int diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigProjectConfigurable.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigProjectConfigurable.kt index c45adba7..ff333f79 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigProjectConfigurable.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigProjectConfigurable.kt @@ -29,9 +29,11 @@ import com.intellij.ui.dsl.builder.Panel class ZigProjectConfigurable(private val project: Project): SubConfigurable { private var settingsPanel: ZigProjectSettingsPanel? = null - override fun createComponent(panel: Panel) { + override fun createComponent(holder: ZigProjectConfigurationProvider.SettingsPanelHolder, panel: Panel): ZigProjectConfigurationProvider.SettingsPanel { settingsPanel?.let { Disposer.dispose(it) } - settingsPanel = ZigProjectSettingsPanel(project).apply { attach(panel) }.also { Disposer.register(this, it) } + val sp = ZigProjectSettingsPanel(holder, project).apply { attach(panel) }.also { Disposer.register(this, it) } + settingsPanel = sp + return sp } override fun isModified(): Boolean { diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigProjectConfigurationProvider.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigProjectConfigurationProvider.kt index 058e18b6..a609a3ee 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigProjectConfigurationProvider.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigProjectConfigurationProvider.kt @@ -32,7 +32,7 @@ import com.intellij.ui.dsl.builder.Panel interface ZigProjectConfigurationProvider { fun handleMainConfigChanged(project: Project) fun createConfigurable(project: Project): SubConfigurable - fun createNewProjectSettingsPanel(): SettingsPanel? + fun createNewProjectSettingsPanel(holder: SettingsPanelHolder): SettingsPanel? val priority: Int companion object { private val EXTENSION_POINT_NAME = ExtensionPointName.create("com.falsepattern.zigbrains.projectConfigProvider") @@ -42,13 +42,17 @@ interface ZigProjectConfigurationProvider { fun createConfigurables(project: Project): List { return EXTENSION_POINT_NAME.extensionList.sortedBy { it.priority }.map { it.createConfigurable(project) } } - fun createNewProjectSettingsPanels(): List { - return EXTENSION_POINT_NAME.extensionList.sortedBy { it.priority }.mapNotNull { it.createNewProjectSettingsPanel() } + fun createNewProjectSettingsPanels(holder: SettingsPanelHolder): List { + return EXTENSION_POINT_NAME.extensionList.sortedBy { it.priority }.mapNotNull { it.createNewProjectSettingsPanel(holder) } } } interface SettingsPanel: Disposable { val data: Settings fun attach(p: Panel) + fun direnvChanged(state: Boolean) + } + interface SettingsPanelHolder { + val panels: List } interface Settings { fun apply(project: Project) diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigProjectSettingsPanel.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigProjectSettingsPanel.kt index d787e0bd..eb3e71c9 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigProjectSettingsPanel.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/project/settings/ZigProjectSettingsPanel.kt @@ -52,9 +52,9 @@ import kotlinx.coroutines.launch import javax.swing.event.DocumentEvent import kotlin.io.path.pathString -class ZigProjectSettingsPanel(private val project: Project) : ZigProjectConfigurationProvider.SettingsPanel { +class ZigProjectSettingsPanel(private val holder: ZigProjectConfigurationProvider.SettingsPanelHolder, private val project: Project) : ZigProjectConfigurationProvider.SettingsPanel { private val direnv = JBCheckBox(ZigBrainsBundle.message("settings.project.label.direnv")).apply { addActionListener { - dispatchAutodetect(true) + dispatchDirenvUpdate() } } private val pathToToolchain = textFieldWithBrowseButton( project, @@ -84,6 +84,16 @@ class ZigProjectSettingsPanel(private val project: Project) : ZigProjectConfigur ).also { Disposer.register(this, it) } private var debounce: Job? = null + private fun dispatchDirenvUpdate() { + holder.panels.forEach { + it.direnvChanged(direnv.isSelected) + } + } + + override fun direnvChanged(state: Boolean) { + dispatchAutodetect(true) + } + private fun dispatchAutodetect(force: Boolean) { project.zigCoroutineScope.launchWithEDT { withModalProgress(ModalTaskOwner.component(pathToToolchain), "Detecting Zig...", TaskCancellation.cancellable()) { diff --git a/core/src/main/kotlin/com/falsepattern/zigbrains/shared/MultiConfigurable.kt b/core/src/main/kotlin/com/falsepattern/zigbrains/shared/MultiConfigurable.kt index 97c22e0a..36c30c13 100644 --- a/core/src/main/kotlin/com/falsepattern/zigbrains/shared/MultiConfigurable.kt +++ b/core/src/main/kotlin/com/falsepattern/zigbrains/shared/MultiConfigurable.kt @@ -22,17 +22,19 @@ package com.falsepattern.zigbrains.shared +import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider import com.intellij.openapi.options.Configurable import com.intellij.openapi.util.Disposer import com.intellij.ui.dsl.builder.panel import javax.swing.JComponent -abstract class MultiConfigurable(private val configurables: List): Configurable { +abstract class MultiConfigurable(val configurables: List): Configurable, ZigProjectConfigurationProvider.SettingsPanelHolder { + final override var panels: List = emptyList() + private set + override fun createComponent(): JComponent? { return panel { - for (configurable in configurables) { - configurable.createComponent(this) - } + panels = configurables.map { it.createComponent(this@MultiConfigurable, this@panel) } } } @@ -50,5 +52,6 @@ abstract class MultiConfigurable(private val configurables: List if (zlsPath.isEmpty()) { - val env = if (state.direnv) project.getDirenv() else emptyEnv + val env = if (project.zigProjectSettings.state.direnv) project.getDirenv() else emptyEnv env.findExecutableOnPATH("zls") ?: run { Notification( "zigbrains-lsp", diff --git a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSProjectSettingsService.kt b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSProjectSettingsService.kt index 5536bf4a..18039240 100644 --- a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSProjectSettingsService.kt +++ b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSProjectSettingsService.kt @@ -26,6 +26,7 @@ import com.falsepattern.zigbrains.direnv.emptyEnv import com.falsepattern.zigbrains.direnv.getDirenv import com.falsepattern.zigbrains.lsp.ZLSBundle import com.falsepattern.zigbrains.lsp.startLSP +import com.falsepattern.zigbrains.project.settings.zigProjectSettings import com.intellij.openapi.components.* import com.intellij.openapi.project.Project import com.intellij.openapi.util.io.toNioPathOrNull @@ -96,7 +97,7 @@ class ZLSProjectSettingsService(val project: Project): PersistentStateComponent< private suspend fun doValidate(project: Project, state: ZLSSettings): Boolean { val zlsPath: Path = state.zlsPath.let { zlsPath -> if (zlsPath.isEmpty()) { - val env = if (state.direnv) project.getDirenv() else emptyEnv + val env = if (project.zigProjectSettings.state.direnv) project.getDirenv() else emptyEnv env.findExecutableOnPATH("zls") ?: run { return false } diff --git a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettings.kt b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettings.kt index 388e2007..d7f2f26e 100644 --- a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettings.kt +++ b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettings.kt @@ -29,7 +29,6 @@ import org.jetbrains.annotations.NonNls @Suppress("PropertyName") data class ZLSSettings( - var direnv: Boolean = false, var zlsPath: @NonNls String = "", var zlsConfigPath: @NonNls String = "", val inlayHints: Boolean = true, diff --git a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettingsConfigurable.kt b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettingsConfigurable.kt index 85363a92..fad06b27 100644 --- a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettingsConfigurable.kt +++ b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettingsConfigurable.kt @@ -22,6 +22,7 @@ package com.falsepattern.zigbrains.lsp.settings +import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider import com.falsepattern.zigbrains.shared.SubConfigurable import com.intellij.openapi.project.Project import com.intellij.openapi.util.Disposer @@ -29,8 +30,10 @@ import com.intellij.ui.dsl.builder.Panel class ZLSSettingsConfigurable(private val project: Project): SubConfigurable { private var appSettingsComponent: ZLSSettingsPanel? = null - override fun createComponent(panel: Panel) { - appSettingsComponent = ZLSSettingsPanel(project).apply { attach(panel) }.also { Disposer.register(this, it) } + override fun createComponent(holder: ZigProjectConfigurationProvider.SettingsPanelHolder, panel: Panel): ZigProjectConfigurationProvider.SettingsPanel { + val settingsPanel = ZLSSettingsPanel(project).apply { attach(panel) }.also { Disposer.register(this, it) } + appSettingsComponent = settingsPanel + return settingsPanel } override fun isModified(): Boolean { diff --git a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettingsPanel.kt b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettingsPanel.kt index 254e8ec3..8ef2dc17 100644 --- a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettingsPanel.kt +++ b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettingsPanel.kt @@ -29,6 +29,7 @@ import com.falsepattern.zigbrains.direnv.getDirenv import com.falsepattern.zigbrains.lsp.ZLSBundle import com.falsepattern.zigbrains.lsp.config.SemanticTokens import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider +import com.falsepattern.zigbrains.project.settings.zigProjectSettings import com.falsepattern.zigbrains.shared.cli.call import com.falsepattern.zigbrains.shared.cli.createCommandLineSafe import com.falsepattern.zigbrains.shared.coroutine.launchWithEDT @@ -87,6 +88,8 @@ class ZLSSettingsPanel(private val project: Project) : ZigProjectConfigurationPr private var debounce: Job? = null + private var direnv: Boolean = project.zigProjectSettings.state.direnv + private val inlayHints = JBCheckBox() private val enable_snippets = JBCheckBox() private val enable_argument_placeholders = JBCheckBox() @@ -109,12 +112,6 @@ class ZLSSettingsPanel(private val project: Project) : ZigProjectConfigurationPr private val build_runner_path = ExtendableTextField() private val global_cache_path = ExtendableTextField() - private val direnv = JBCheckBox(ZLSBundle.message("settings.zls-path.use-direnv.label")).apply { - addActionListener { - dispatchAutodetect(true) - } - } - override fun attach(p: Panel) = with(p) { if (!project.isDefault) { group(ZLSBundle.message("settings.group.title")) { @@ -123,9 +120,6 @@ class ZLSSettingsPanel(private val project: Project) : ZigProjectConfigurationPr "settings.zls-path.tooltip" ) { cell(zlsPath).resizableColumn().align(AlignX.FILL) - if (DirenvCmd.direnvInstalled()) { - cell(direnv) - } } row(ZLSBundle.message("settings.zls-version.label")) { cell(zlsVersion) @@ -225,9 +219,13 @@ class ZLSSettingsPanel(private val project: Project) : ZigProjectConfigurationPr dispatchAutodetect(false) } + override fun direnvChanged(state: Boolean) { + direnv = state + dispatchAutodetect(true) + } + override var data get() = ZLSSettings( - direnv.isSelected, zlsPath.text, zlsConfigPath.text, inlayHints.isSelected, @@ -253,7 +251,6 @@ class ZLSSettingsPanel(private val project: Project) : ZigProjectConfigurationPr global_cache_path.text?.ifBlank { null }, ) set(value) { - direnv.isSelected = value.direnv zlsPath.text = value.zlsPath zlsConfigPath.text = value.zlsConfigPath inlayHints.isSelected = value.inlayHints @@ -305,7 +302,7 @@ class ZLSSettingsPanel(private val project: Project) : ZigProjectConfigurationPr } private suspend fun getDirenv(): Env { - if (!project.isDefault && DirenvCmd.direnvInstalled() && direnv.isSelected) + if (!project.isDefault && DirenvCmd.direnvInstalled() && direnv) return project.getDirenv() return emptyEnv }