diff --git a/CHANGELOG.md b/CHANGELOG.md index 2562a50c..a5bbae90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,16 @@ Changelog structure reference: ## [Unreleased] +### Added + +- ZLS + - All of the config options are now exposed in the GUI + +### Changed + +- Project + - New project panel is now much more compact + ## [20.3.0] - Zig 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 7c39a25e..d8a76a88 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 @@ -24,6 +24,7 @@ package com.falsepattern.zigbrains.project.settings import com.falsepattern.zigbrains.shared.SubConfigurable import com.intellij.openapi.project.Project +import com.intellij.openapi.project.ProjectManager class ZigCoreProjectConfigurationProvider: ZigProjectConfigurationProvider { override fun handleMainConfigChanged(project: Project) { @@ -34,7 +35,7 @@ class ZigCoreProjectConfigurationProvider: ZigProjectConfigurationProvider { } override fun createNewProjectSettingsPanel(): ZigProjectConfigurationProvider.SettingsPanel { - return ZigProjectSettingsPanel(null) + return ZigProjectSettingsPanel(ProjectManager.getInstance().defaultProject) } override val priority: Int 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 0dc7cfc6..058e18b6 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(): SettingsPanel? val priority: Int companion object { private val EXTENSION_POINT_NAME = ExtensionPointName.create("com.falsepattern.zigbrains.projectConfigProvider") @@ -43,7 +43,7 @@ interface ZigProjectConfigurationProvider { return EXTENSION_POINT_NAME.extensionList.sortedBy { it.priority }.map { it.createConfigurable(project) } } fun createNewProjectSettingsPanels(): List { - return EXTENSION_POINT_NAME.extensionList.sortedBy { it.priority }.map { it.createNewProjectSettingsPanel() } + return EXTENSION_POINT_NAME.extensionList.sortedBy { it.priority }.mapNotNull { it.createNewProjectSettingsPanel() } } } interface SettingsPanel: Disposable { 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 8ea8374e..7f965470 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,7 +52,7 @@ 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 project: Project) : ZigProjectConfigurationProvider.SettingsPanel { private val direnv = JBCheckBox(ZigBrainsBundle.message("settings.project.label.direnv")).apply { addActionListener { dispatchAutodetect(true) } } @@ -96,7 +96,7 @@ class ZigProjectSettingsPanel(private val project: Project?) : ZigProjectConfigu if (!force && pathToToolchain.text.isNotBlank()) return val data = UserDataHolderBase() - data.putUserData(LocalZigToolchain.DIRENV_KEY, DirenvCmd.direnvInstalled() && project?.isDefault == false && direnv.isSelected) + data.putUserData(LocalZigToolchain.DIRENV_KEY, !project.isDefault && direnv.isSelected && DirenvCmd.direnvInstalled()) val tc = ZigToolchainProvider.suggestToolchain(project, data) ?: return if (tc !is LocalZigToolchain) { TODO("Implement non-local zig toolchain in config") @@ -124,21 +124,29 @@ class ZigProjectSettingsPanel(private val project: Project?) : ZigProjectConfigu } override fun attach(p: Panel): Unit = with(p) { - val project = project ?: ProjectManager.getInstance().defaultProject data = project.zigProjectSettings.state - group(ZigBrainsBundle.message("settings.project.group.title")) { + if (project.isDefault) { row(ZigBrainsBundle.message("settings.project.label.toolchain")) { cell(pathToToolchain).resizableColumn().align(AlignX.FILL) - if (DirenvCmd.direnvInstalled() && !project.isDefault) { - cell(direnv) - } } row(ZigBrainsBundle.message("settings.project.label.toolchain-version")) { cell(toolchainVersion) } - row(ZigBrainsBundle.message("settings.project.label.std-location")) { - cell(pathToStd).resizableColumn().align(AlignX.FILL) - cell(stdFieldOverride) + } else { + group(ZigBrainsBundle.message("settings.project.group.title")) { + row(ZigBrainsBundle.message("settings.project.label.toolchain")) { + cell(pathToToolchain).resizableColumn().align(AlignX.FILL) + if (DirenvCmd.direnvInstalled()) { + cell(direnv) + } + } + row(ZigBrainsBundle.message("settings.project.label.toolchain-version")) { + cell(toolchainVersion) + } + row(ZigBrainsBundle.message("settings.project.label.std-location")) { + cell(pathToStd).resizableColumn().align(AlignX.FILL) + cell(stdFieldOverride) + } } } dispatchAutodetect(false) diff --git a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/ZLSProjectConfigurationProvider.kt b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/ZLSProjectConfigurationProvider.kt index 52702747..5ce04806 100644 --- a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/ZLSProjectConfigurationProvider.kt +++ b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/ZLSProjectConfigurationProvider.kt @@ -27,6 +27,7 @@ import com.falsepattern.zigbrains.lsp.settings.ZLSSettingsPanel import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider import com.falsepattern.zigbrains.shared.SubConfigurable import com.intellij.openapi.project.Project +import com.intellij.openapi.project.ProjectManager class ZLSProjectConfigurationProvider: ZigProjectConfigurationProvider { override fun handleMainConfigChanged(project: Project) { @@ -38,7 +39,7 @@ class ZLSProjectConfigurationProvider: ZigProjectConfigurationProvider { } override fun createNewProjectSettingsPanel(): ZigProjectConfigurationProvider.SettingsPanel { - return ZLSSettingsPanel(null) + return ZLSSettingsPanel(ProjectManager.getInstance().defaultProject) } override val priority: Int diff --git a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/ZLSStreamConnectionProvider.kt b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/ZLSStreamConnectionProvider.kt index 496618d2..7048c887 100644 --- a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/ZLSStreamConnectionProvider.kt +++ b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/ZLSStreamConnectionProvider.kt @@ -51,28 +51,7 @@ import kotlin.io.path.isRegularFile import kotlin.io.path.pathString class ZLSStreamConnectionProvider private constructor(private val project: Project, commandLine: GeneralCommandLine?) : OSProcessStreamConnectionProvider(commandLine) { - override fun handleMessage(message: Message?, languageServer: LanguageServer?, rootUri: VirtualFile?) { - if (project.zlsSettings.state.inlayHintsCompact) { - if (message is ResponseMessage) { - val res = message.result - if (res is Collection<*>) { - res.forEach { e -> - if (e is InlayHint) { - tryMutateInlayHint(e) - } - } - } else if (res is InlayHint) { - tryMutateInlayHint(res) - } - } - } - super.handleMessage(message, languageServer, rootUri) - } - companion object { - private val LOG = Logger.getInstance(ZLSStreamConnectionProvider::class.java) - private val ERROR_BLOCK = Regex("error\\{.*?}", RegexOption.DOT_MATCHES_ALL) - suspend fun create(project: Project): ZLSStreamConnectionProvider { val projectDir = project.guessProjectDir()?.toNioPathOrNull() val commandLine = getCommand(project)?.let { GeneralCommandLine(it) }?.withWorkingDirectory(projectDir) @@ -154,7 +133,7 @@ class ZLSStreamConnectionProvider private constructor(private val project: Proje } } ?: run { val config = ZLSConfigProviderBase.findEnvironment(project) - if (config.zigExePath.isNullOrEmpty() || config.zigLibPath.isNullOrEmpty()) { + if (config.zig_exe_path.isNullOrEmpty() || config.zig_lib_path.isNullOrEmpty()) { Notification( "zigbrains-lsp", ZLSBundle.message("notification.message.zls-config-autogen-failed.content"), @@ -174,14 +153,6 @@ class ZLSStreamConnectionProvider private constructor(private val project: Proje cmd.add(configPath.pathString) } - if (state.debug) { - cmd.add("--enable-debug-log") - } - - if (state.messageTrace) { - cmd.add("--enable-message-tracing") - } - if (SystemInfo.isWindows) { val sb: StringBuilder by lazy { StringBuilder() } for (i in 0.. = emptyList(), + val semantic_tokens: SemanticTokens = SemanticTokens.full, + val inlay_hints_show_variable_type_hints: Boolean = true, + val inlay_hints_show_struct_literal_field_type: Boolean = true, + val inlay_hints_show_parameter_name: Boolean = true, + val inlay_hints_show_builtin: Boolean = true, + val inlay_hints_exclude_single_argument: Boolean = true, + val inlay_hints_hide_redundant_param_names: Boolean = false, + val inlay_hints_hide_redundant_param_names_last_token: Boolean = false, + val force_autofix: Boolean = false, + val warn_style: Boolean = false, + val highlight_global_var_declarations: Boolean = false, + val skip_std_references: Boolean = false, + val prefer_ast_check_as_child_process: Boolean = true, + val builtin_path: String? = null, + val zig_lib_path: @NonNls String? = null, + val zig_exe_path: @NonNls String? = null, + val build_runner_path: @NonNls String? = null, + val global_cache_path: @NonNls String? = null, ) +enum class SemanticTokens { + none, + partial, + full, +} 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 acac2a9e..51c29771 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 @@ -22,22 +22,38 @@ package com.falsepattern.zigbrains.lsp.settings +import com.falsepattern.zigbrains.lsp.config.SemanticTokens +import com.falsepattern.zigbrains.lsp.config.ZLSConfig import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider import com.intellij.openapi.project.Project import org.jetbrains.annotations.NonNls +@Suppress("PropertyName") data class ZLSSettings( var direnv: Boolean = false, var zlsPath: @NonNls String = "", var zlsConfigPath: @NonNls String = "", - var debug: Boolean = false, - var messageTrace: Boolean = false, - var buildOnSave: Boolean = false, - var buildOnSaveStep: @NonNls String = "install", - var globalVarDeclarations: Boolean = false, - var comptimeInterpreter: Boolean = false, - var inlayHints: Boolean = true, - var inlayHintsCompact: Boolean = true + val inlayHints: Boolean = true, + val enable_snippets: Boolean = true, + val enable_argument_placeholders: Boolean = true, + val completion_label_details: Boolean = true, + val enable_build_on_save: Boolean = false, + val build_on_save_args: List = emptyList(), + val semantic_tokens: SemanticTokens = SemanticTokens.full, + val inlay_hints_show_variable_type_hints: Boolean = true, + val inlay_hints_show_struct_literal_field_type: Boolean = true, + val inlay_hints_show_parameter_name: Boolean = true, + val inlay_hints_show_builtin: Boolean = true, + val inlay_hints_exclude_single_argument: Boolean = true, + val inlay_hints_hide_redundant_param_names: Boolean = false, + val inlay_hints_hide_redundant_param_names_last_token: Boolean = false, + val warn_style: Boolean = false, + val highlight_global_var_declarations: Boolean = false, + val skip_std_references: Boolean = false, + val prefer_ast_check_as_child_process: Boolean = true, + val builtin_path: String? = null, + val build_runner_path: @NonNls String? = null, + val global_cache_path: @NonNls String? = null, ): ZigProjectConfigurationProvider.Settings { override fun apply(project: Project) { project.zlsSettings.loadState(this) diff --git a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettingsConfigProvider.kt b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettingsConfigProvider.kt index ae1798c3..5d42ab13 100644 --- a/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettingsConfigProvider.kt +++ b/lsp/src/main/kotlin/com/falsepattern/zigbrains/lsp/settings/ZLSSettingsConfigProvider.kt @@ -30,10 +30,26 @@ class ZLSSettingsConfigProvider: ZLSConfigProvider { override fun getEnvironment(project: Project, previous: ZLSConfig): ZLSConfig { val state = project.zlsSettings.state return previous.copy( - buildOnSave = state.buildOnSave, - buildOnSaveStep = state.buildOnSaveStep, - globalVarDeclarations = state.globalVarDeclarations, - comptimeInterpreter = state.comptimeInterpreter + enable_snippets = state.enable_snippets, + enable_argument_placeholders = state.enable_argument_placeholders, + completion_label_details = state.completion_label_details, + enable_build_on_save = state.enable_build_on_save, + build_on_save_args = state.build_on_save_args, + semantic_tokens = state.semantic_tokens, + inlay_hints_show_variable_type_hints = state.inlay_hints_show_variable_type_hints, + inlay_hints_show_struct_literal_field_type = state.inlay_hints_show_struct_literal_field_type, + inlay_hints_show_parameter_name = state.inlay_hints_show_parameter_name, + inlay_hints_show_builtin = state.inlay_hints_show_builtin, + inlay_hints_exclude_single_argument = state.inlay_hints_exclude_single_argument, + inlay_hints_hide_redundant_param_names = state.inlay_hints_hide_redundant_param_names, + inlay_hints_hide_redundant_param_names_last_token = state.inlay_hints_hide_redundant_param_names_last_token, + warn_style = state.warn_style, + highlight_global_var_declarations = state.highlight_global_var_declarations, + skip_std_references = state.skip_std_references, + prefer_ast_check_as_child_process = state.prefer_ast_check_as_child_process, + builtin_path = state.builtin_path, + build_runner_path = state.build_runner_path, + global_cache_path = state.global_cache_path, ) } } \ No newline at end of file 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 6860f372..0af475d6 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 @@ -27,12 +27,13 @@ import com.falsepattern.zigbrains.direnv.Env import com.falsepattern.zigbrains.direnv.emptyEnv 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.shared.coroutine.launchWithEDT import com.falsepattern.zigbrains.shared.zigCoroutineScope -import com.intellij.openapi.Disposable import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory import com.intellij.openapi.project.Project +import com.intellij.openapi.ui.ComboBox import com.intellij.openapi.util.Disposer import com.intellij.platform.ide.progress.ModalTaskOwner import com.intellij.platform.ide.progress.TaskCancellation @@ -42,50 +43,157 @@ import com.intellij.ui.components.fields.ExtendableTextField import com.intellij.ui.components.textFieldWithBrowseButton import com.intellij.ui.dsl.builder.AlignX import com.intellij.ui.dsl.builder.Panel +import com.intellij.ui.dsl.builder.Row +import com.jetbrains.rd.generator.nova.GenerationSpec.Companion.nullIfEmpty +import org.jetbrains.annotations.PropertyKey +import java.lang.IllegalArgumentException +import java.util.* import kotlin.io.path.pathString -class ZLSSettingsPanel(private val project: Project?) : ZigProjectConfigurationProvider.SettingsPanel { +@Suppress("PrivatePropertyName") +class ZLSSettingsPanel(private val project: Project) : ZigProjectConfigurationProvider.SettingsPanel { private val zlsPath = textFieldWithBrowseButton( project, - FileChooserDescriptorFactory.createSingleFileDescriptor().withTitle(ZLSBundle.message("settings.zls-path.browse.title")), + FileChooserDescriptorFactory.createSingleFileDescriptor() + .withTitle(ZLSBundle.message("settings.zls-path.browse.title")), ).also { Disposer.register(this, it) } private val zlsConfigPath = textFieldWithBrowseButton( project, - FileChooserDescriptorFactory.createSingleFileDescriptor().withTitle(ZLSBundle.message("settings.zls-config-path.browse.title")) + FileChooserDescriptorFactory.createSingleFileDescriptor() + .withTitle(ZLSBundle.message("settings.zls-config-path.browse.title")) ).also { Disposer.register(this, it) } - private val buildOnSave = JBCheckBox().apply { toolTipText = ZLSBundle.message("settings.build-on-save.tooltip") } - private val buildOnSaveStep = ExtendableTextField().apply { toolTipText = ZLSBundle.message("settings.build-on-save-step.tooltip") } - private val globalVarDeclarations = JBCheckBox() - private val comptimeInterpreter = JBCheckBox() private val inlayHints = JBCheckBox() - private val inlayHintsCompact = JBCheckBox().apply { toolTipText = ZLSBundle.message("settings.inlay-hints-compact.tooltip") } + private val enable_snippets = JBCheckBox() + private val enable_argument_placeholders = JBCheckBox() + private val completion_label_details = JBCheckBox() + private val enable_build_on_save = JBCheckBox() + private val build_on_save_args = ExtendableTextField() + private val semantic_tokens = ComboBox(SemanticTokens.entries.toTypedArray()) + private val inlay_hints_show_variable_type_hints = JBCheckBox() + private val inlay_hints_show_struct_literal_field_type = JBCheckBox() + private val inlay_hints_show_parameter_name = JBCheckBox() + private val inlay_hints_show_builtin = JBCheckBox() + private val inlay_hints_exclude_single_argument = JBCheckBox() + private val inlay_hints_hide_redundant_param_names = JBCheckBox() + private val inlay_hints_hide_redundant_param_names_last_token = JBCheckBox() + private val warn_style = JBCheckBox() + private val highlight_global_var_declarations = JBCheckBox() + private val skip_std_references = JBCheckBox() + private val prefer_ast_check_as_child_process = JBCheckBox() + private val builtin_path = ExtendableTextField() + private val build_runner_path = ExtendableTextField() + private val global_cache_path = ExtendableTextField() - private val messageTrace = JBCheckBox() - private val debug = JBCheckBox() - private val direnv = JBCheckBox(ZLSBundle.message("settings.zls-path.use-direnv.label")).apply { addActionListener { - dispatchAutodetect(true) - } } - - override fun attach(panel: Panel) = with(panel) { - group(ZLSBundle.message("settings.group.title")) { - row(ZLSBundle.message("settings.zls-path.label")) { - cell(zlsPath).resizableColumn().align(AlignX.FILL) - if (DirenvCmd.direnvInstalled() && project?.isDefault == false) { - cell(direnv) - } - } - row(ZLSBundle.message("settings.zls-config-path.label")) { cell(zlsConfigPath).align(AlignX.FILL) } - row(ZLSBundle.message("settings.inlay-hints.label")) { cell(inlayHints) } - row(ZLSBundle.message("settings.inlay-hints-compact.label")) { cell(inlayHintsCompact) } - row(ZLSBundle.message("settings.build-on-save.label")) { cell(buildOnSave) } - row(ZLSBundle.message("settings.build-on-save-step.label")) { cell(buildOnSaveStep).resizableColumn().align(AlignX.FILL) } - row(ZLSBundle.message("settings.global-var-declarations.label")) { cell(globalVarDeclarations) } - row(ZLSBundle.message("settings.comptime-interpreter.label")) { cell(comptimeInterpreter) } + private val direnv = JBCheckBox(ZLSBundle.message("settings.zls-path.use-direnv.label")).apply { + addActionListener { + dispatchAutodetect(true) } - group(ZLSBundle.message("dev-settings.group.title")) { - row(ZLSBundle.message("dev-settings.debug.label")) { cell(debug) } - row(ZLSBundle.message("dev-settings.message-trace.label")) { cell(messageTrace) } + } + + override fun attach(p: Panel) = with(p) { + if (!project.isDefault) { + group(ZLSBundle.message("settings.group.title")) { + fancyRow( + "settings.zls-path.label", + "settings.zls-path.tooltip" + ) { + cell(zlsPath).resizableColumn().align(AlignX.FILL) + if (DirenvCmd.direnvInstalled()) { + cell(direnv) + } + } + fancyRow( + "settings.zls-config-path.label", + "settings.zls-config-path.tooltip" + ) { cell(zlsConfigPath).align(AlignX.FILL) } + fancyRow( + "settings.enable_snippets.label", + "settings.enable_snippets.tooltip" + ) { cell(enable_snippets) } + fancyRow( + "settings.enable_argument_placeholders.label", + "settings.enable_argument_placeholders.tooltip" + ) { cell(enable_argument_placeholders) } + fancyRow( + "settings.completion_label_details.label", + "settings.completion_label_details.tooltip" + ) { cell(completion_label_details) } + fancyRow( + "settings.enable_build_on_save.label", + "settings.enable_build_on_save.tooltip" + ) { cell(enable_build_on_save) } + fancyRow( + "settings.build_on_save_args.label", + "settings.build_on_save_args.tooltip" + ) { cell(build_on_save_args).resizableColumn().align(AlignX.FILL) } + fancyRow( + "settings.semantic_tokens.label", + "settings.semantic_tokens.tooltip" + ) { cell(semantic_tokens) } + group(ZLSBundle.message("settings.inlay-hints-group.label")) { + fancyRow( + "settings.inlay-hints-enable.label", + "settings.inlay-hints-enable.tooltip" + ) { cell(inlayHints) } + fancyRow( + "settings.inlay_hints_show_variable_type_hints.label", + "settings.inlay_hints_show_variable_type_hints.tooltip" + ) { cell(inlay_hints_show_variable_type_hints) } + fancyRow( + "settings.inlay_hints_show_struct_literal_field_type.label", + "settings.inlay_hints_show_struct_literal_field_type.tooltip" + ) { cell(inlay_hints_show_struct_literal_field_type) } + fancyRow( + "settings.inlay_hints_show_parameter_name.label", + "settings.inlay_hints_show_parameter_name.tooltip" + ) { cell(inlay_hints_show_parameter_name) } + fancyRow( + "settings.inlay_hints_show_builtin.label", + "settings.inlay_hints_show_builtin.tooltip" + ) { cell(inlay_hints_show_builtin) } + fancyRow( + "settings.inlay_hints_exclude_single_argument.label", + "settings.inlay_hints_exclude_single_argument.tooltip" + ) { cell(inlay_hints_exclude_single_argument) } + fancyRow( + "settings.inlay_hints_hide_redundant_param_names.label", + "settings.inlay_hints_hide_redundant_param_names.tooltip" + ) { cell(inlay_hints_hide_redundant_param_names) } + fancyRow( + "settings.inlay_hints_hide_redundant_param_names_last_token.label", + "settings.inlay_hints_hide_redundant_param_names_last_token.tooltip" + ) { cell(inlay_hints_hide_redundant_param_names_last_token) } + } + fancyRow( + "settings.warn_style.label", + "settings.warn_style.tooltip" + ) { cell(warn_style) } + fancyRow( + "settings.highlight_global_var_declarations.label", + "settings.highlight_global_var_declarations.tooltip" + ) { cell(highlight_global_var_declarations) } + fancyRow( + "settings.skip_std_references.label", + "settings.skip_std_references.tooltip" + ) { cell(skip_std_references) } + fancyRow( + "settings.prefer_ast_check_as_child_process.label", + "settings.prefer_ast_check_as_child_process.tooltip" + ) { cell(prefer_ast_check_as_child_process) } + fancyRow( + "settings.builtin_path.label", + "settings.builtin_path.tooltip" + ) { cell(builtin_path).resizableColumn().align(AlignX.FILL) } + fancyRow( + "settings.build_runner_path.label", + "settings.build_runner_path.tooltip" + ) { cell(build_runner_path).resizableColumn().align(AlignX.FILL) } + fancyRow( + "settings.global_cache_path.label", + "settings.global_cache_path.tooltip" + ) { cell(global_cache_path).resizableColumn().align(AlignX.FILL) } + } } dispatchAutodetect(false) } @@ -95,27 +203,61 @@ class ZLSSettingsPanel(private val project: Project?) : ZigProjectConfigurationP direnv.isSelected, zlsPath.text, zlsConfigPath.text, - debug.isSelected, - messageTrace.isSelected, - buildOnSave.isSelected, - buildOnSaveStep.text, - globalVarDeclarations.isSelected, - comptimeInterpreter.isSelected, inlayHints.isSelected, - inlayHintsCompact.isSelected + enable_snippets.isSelected, + enable_argument_placeholders.isSelected, + completion_label_details.isSelected, + enable_build_on_save.isSelected, + run { + val args = build_on_save_args.text ?: "" + return@run if (args.isEmpty()) { + emptyList() + } else { + translateCommandline(args).toList() + } + }, + semantic_tokens.item ?: SemanticTokens.full, + inlay_hints_show_variable_type_hints.isSelected, + inlay_hints_show_struct_literal_field_type.isSelected, + inlay_hints_show_parameter_name.isSelected, + inlay_hints_show_builtin.isSelected, + inlay_hints_exclude_single_argument.isSelected, + inlay_hints_hide_redundant_param_names.isSelected, + inlay_hints_hide_redundant_param_names_last_token.isSelected, + warn_style.isSelected, + highlight_global_var_declarations.isSelected, + skip_std_references.isSelected, + prefer_ast_check_as_child_process.isSelected, + builtin_path.text?.nullIfEmpty(), + build_runner_path.text?.nullIfEmpty(), + global_cache_path.text?.nullIfEmpty(), ) set(value) { direnv.isSelected = value.direnv zlsPath.text = value.zlsPath zlsConfigPath.text = value.zlsConfigPath - debug.isSelected = value.debug - messageTrace.isSelected = value.messageTrace - buildOnSave.isSelected = value.buildOnSave - buildOnSaveStep.text = value.buildOnSaveStep - globalVarDeclarations.isSelected = value.globalVarDeclarations - comptimeInterpreter.isSelected = value.comptimeInterpreter inlayHints.isSelected = value.inlayHints - inlayHintsCompact.isSelected = value.inlayHintsCompact + enable_snippets.isSelected = value.enable_snippets + enable_argument_placeholders.isSelected = value.enable_argument_placeholders + completion_label_details.isSelected = value.completion_label_details + enable_build_on_save.isSelected = value.enable_build_on_save + build_on_save_args.text = value.build_on_save_args.joinToString(separator = " ") { it } + semantic_tokens.item = value.semantic_tokens + inlay_hints_show_variable_type_hints.isSelected = value.inlay_hints_show_variable_type_hints + inlay_hints_show_struct_literal_field_type.isSelected = value.inlay_hints_show_struct_literal_field_type + inlay_hints_show_parameter_name.isSelected = value.inlay_hints_show_parameter_name + inlay_hints_show_builtin.isSelected = value.inlay_hints_show_builtin + inlay_hints_exclude_single_argument.isSelected = value.inlay_hints_exclude_single_argument + inlay_hints_hide_redundant_param_names.isSelected = value.inlay_hints_hide_redundant_param_names + inlay_hints_hide_redundant_param_names_last_token.isSelected = + value.inlay_hints_hide_redundant_param_names_last_token + warn_style.isSelected = value.warn_style + highlight_global_var_declarations.isSelected = value.highlight_global_var_declarations + skip_std_references.isSelected = value.skip_std_references + prefer_ast_check_as_child_process.isSelected = value.prefer_ast_check_as_child_process + builtin_path.text = value.builtin_path ?: "" + build_runner_path.text = value.build_runner_path ?: "" + global_cache_path.text = value.global_cache_path ?: "" } private fun dispatchAutodetect(force: Boolean) { @@ -140,8 +282,93 @@ class ZLSSettingsPanel(private val project: Project?) : ZigProjectConfigurationP } private suspend fun getDirenv(): Env { - if (DirenvCmd.direnvInstalled() && project?.isDefault == false && direnv.isSelected) + if (!project.isDefault && DirenvCmd.direnvInstalled() && direnv.isSelected) return project.getDirenv() return emptyEnv } -} \ No newline at end of file +} + +private fun Panel.fancyRow( + label: @PropertyKey(resourceBundle = "zigbrains.lsp.Bundle") String, + tooltip: @PropertyKey(resourceBundle = "zigbrains.lsp.Bundle") String, + cb: Row.() -> Unit +) = row(ZLSBundle.message(label)) { + contextHelp(ZLSBundle.message(tooltip)) + cb() +} + + +@Throws(Exception::class) +private fun translateCommandline(toProcess: String): List { + if (toProcess.isEmpty()) { + return emptyList() + } + val normal = 0 + val inQuote = 1 + val inDoubleQuote = 2 + val inEscape = 3 + var state = normal + var escapeState = normal + val tok = StringTokenizer(toProcess, "\\\"' ", true) + val v = ArrayList() + val current = StringBuilder() + + while (tok.hasMoreTokens()) { + val nextTok = tok.nextToken() + when (state) { + inQuote -> if ("'" == nextTok) { + state = normal + } else if ("\\" == nextTok) { + escapeState = inQuote + state = inEscape + } else { + current.append(nextTok) + } + + inDoubleQuote -> if ("\"" == nextTok) { + state = normal + } else if ("\\" == nextTok) { + escapeState = inDoubleQuote + state = inEscape + } else { + current.append(nextTok) + } + + inEscape -> { + current.append(when(nextTok) { + "n" -> "\n" + "r" -> "\r" + "t" -> "\t" + else -> nextTok + }) + state = escapeState + } + + else -> if ("'" == nextTok) { + state = inQuote + } else if ("\"" == nextTok) { + state = inDoubleQuote + } else if (" " == nextTok) { + if (current.isNotEmpty()) { + v.add(current.toString()) + current.setLength(0) + } + } else if ("\\" == nextTok) { + escapeState = normal + state = inEscape + } else { + current.append(nextTok) + } + } + } + + if (current.isNotEmpty()) { + v.add(current.toString()) + } + + if (state != inQuote && state != inDoubleQuote) { + return v + } else { + throw IllegalArgumentException("unbalanced quotes in $toProcess") + } +} diff --git a/lsp/src/main/kotlin/com/falsepattern/zigbrains/project/toolchain/ToolchainZLSConfigProvider.kt b/lsp/src/main/kotlin/com/falsepattern/zigbrains/project/toolchain/ToolchainZLSConfigProvider.kt index 067cd34d..a4b2f878 100644 --- a/lsp/src/main/kotlin/com/falsepattern/zigbrains/project/toolchain/ToolchainZLSConfigProvider.kt +++ b/lsp/src/main/kotlin/com/falsepattern/zigbrains/project/toolchain/ToolchainZLSConfigProvider.kt @@ -81,6 +81,6 @@ class ToolchainZLSConfigProvider: SuspendingZLSConfigProvider { if (lib == null) return previous - return previous.copy(zigExePath = exe.pathString, zigLibPath = lib.pathString) + return previous.copy(zig_exe_path = exe.pathString, zig_lib_path = lib.pathString) } } \ No newline at end of file diff --git a/lsp/src/main/resources/META-INF/zigbrains-lsp.xml b/lsp/src/main/resources/META-INF/zigbrains-lsp.xml index 22e47143..bc291342 100644 --- a/lsp/src/main/resources/META-INF/zigbrains-lsp.xml +++ b/lsp/src/main/resources/META-INF/zigbrains-lsp.xml @@ -21,7 +21,6 @@ --> - zigbrains.lsp.Bundle Zig Language Server, via ZigBrains \ No newline at end of file +lsp.zls.description=The Zig Language Server, via ZigBrains