Compare commits

..

24 commits

Author SHA1 Message Date
0032dbf0f3
ci: 25.2.0 2025-04-20 16:10:20 +02:00
e7f0bb793a
feat: build.zig integration for run and test line markers 2025-04-20 15:57:37 +02:00
532292068f
feat: debugger improved error message for failed compilation 2025-04-20 15:56:21 +02:00
dd2104065c
ci: update push.sh 2025-04-17 13:57:44 +02:00
8389c66814
ci: 25.1.0 2025-04-17 13:53:19 +02:00
803b25d7fb
fix: [NO BACKPORT] update cpp debugger resolution logic 2025-04-17 13:43:08 +02:00
b3ce6d62a7
ci: add 251 to build and docs 2025-04-17 13:43:08 +02:00
f28cf77347
ci: [NO BACKPORT] switch to IDE 2025.1 2025-04-17 13:42:57 +02:00
c524bbf899
feat: Inlay hint file size limit option 2025-04-17 09:39:10 +02:00
a9c8a3a0d9
ci: 25.0.2 2025-04-16 00:42:41 +02:00
570eeac755
chore: fix some kotlin linter warnings 2025-04-16 00:42:34 +02:00
5efc28ae18
chore: cache suggestion paths 2025-04-16 00:31:25 +02:00
91747319aa
fix: non-scrollable ZLS settings 2025-04-16 00:17:02 +02:00
8a7ca04168
ci: 25.0.1 emergency hotfix 2025-04-11 18:51:27 +02:00
5e4f2d5dfb
ci: 25.0.0 2025-04-11 18:00:43 +02:00
4722613b4c
chore: optimize imports 2025-04-11 18:00:35 +02:00
53f4d1d330
feat: Hide library root if zig not configured 2025-04-11 17:47:33 +02:00
270ac9e113
fix: ZLS config not serializing 2025-04-11 17:32:58 +02:00
a4db054b59
fix: Config shows changed when not yet initialized 2025-04-11 17:32:46 +02:00
bd47cb201f
chore: Add lang for ZLS management 2025-04-11 17:19:54 +02:00
520167414a
docs: update readme 2025-04-11 17:19:52 +02:00
2d0ad8be44
ci: update changelog 2025-04-11 17:19:49 +02:00
9913ceb67e
ci: add etag check to debugger properties download 2025-04-11 17:19:48 +02:00
d5359e5816
feat!: Toolchain rework 2025-04-11 17:19:44 +02:00
74 changed files with 473 additions and 351 deletions

View file

@ -17,6 +17,55 @@ Changelog structure reference:
## [Unreleased] ## [Unreleased]
## [25.2.0]
### Added
- Debugger
- Notify the user if zig run / zig test debugging starts, but a build.zig is present
### Changed
- Project
- Line marker task suggestions for main/test now defer to Zig Build if build.zig file is detected.
### Fixed
- Debugger
- Compilation failures did not open the terminal properly and suppressed the error message
## [25.1.0]
### Added
- IDEA 2025.1 support
- LSP
- Configurable inlay hints file size limit to reduce IDE lag
## [25.0.2]
### Fixed
- Project
- ZLS settings not scrollable in the language server list
## [25.0.1]
### Fixed
- Project
- Zig.iml file created in every project
### Changed
- Project
- BREAKING MAJOR UPDATE: Fully reworked toolchain and language server management
The configuration menu is now very similar to the intellij java toolchain management,
with proper toolchain selection, detection, downloading, etc. This change will require
you to re-configure your toolchains!
- Zig external library root is now no longer shown if zig is not configured
## [24.0.1] ## [24.0.1]
### Added ### Added

View file

@ -15,6 +15,7 @@ through the built-in plugin browser:
1. Go to `Settings -> Plugins` 1. Go to `Settings -> Plugins`
2. To the right of the `Installed` button at the top, click on the `...` dropdown menu, then select `Manage Plugin Repositories...` 2. To the right of the `Installed` button at the top, click on the `...` dropdown menu, then select `Manage Plugin Repositories...`
3. Click the add button, and then enter the ZigBrains updater URL, based on your IDE version: 3. Click the add button, and then enter the ZigBrains updater URL, based on your IDE version:
- `2025.1.*` or newer: https://falsepattern.com/zigbrains/updatePlugins-251.xml
- `2024.3.*`: https://falsepattern.com/zigbrains/updatePlugins-243.xml - `2024.3.*`: https://falsepattern.com/zigbrains/updatePlugins-243.xml
- `2024.2.*`: https://falsepattern.com/zigbrains/updatePlugins-242.xml - `2024.2.*`: https://falsepattern.com/zigbrains/updatePlugins-242.xml
- `2024.1.*`: https://falsepattern.com/zigbrains/updatePlugins-241.xml - `2024.1.*`: https://falsepattern.com/zigbrains/updatePlugins-241.xml
@ -71,11 +72,7 @@ excellent example on how to write debugger support that doesn't depend on CLion.
<!-- Plugin description --> <!-- Plugin description -->
Adds support for the Zig Language, utilizing the ZLS language server for advanced coding assistance. Adds support for the Zig Language, utilizing the ZLS language server for advanced coding assistance.
## Quick setup guide for Zig and ZLS Before you can properly use the plugin, you need to select or download the Zig toolchain and language server in `Settings` -> `Languages & Frameworks` -> `Zig`.
1. Download the latest version of Zig from https://ziglang.org/download
2. Download and compile the ZLS language server, available at https://github.com/zigtools/zls
3. Go to `Settings` -> `Languages & Frameworks` -> `Zig`, and point the `Toolchain Location` and `ZLS path` to the correct places
## Debugging ## Debugging
@ -89,6 +86,7 @@ Debugging Zig code is supported in any native debugging capable IDE. The followi
- RustRover (including the non-commercial free version too) - RustRover (including the non-commercial free version too)
- GoLand - GoLand
- PyCharm Professional - PyCharm Professional
- Android Studio
Additionally, in CLion, the plugin uses the C++ Toolchains for sourcing the debugger (this can be toggled off in the settings). Additionally, in CLion, the plugin uses the C++ Toolchains for sourcing the debugger (this can be toggled off in the settings).

View file

@ -6,15 +6,15 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
plugins { plugins {
kotlin("jvm") version "2.0.21" apply false kotlin("jvm") version "2.1.10" apply false
kotlin("plugin.serialization") version "2.0.21" apply false kotlin("plugin.serialization") version "2.1.10" apply false
id("org.jetbrains.intellij.platform") version "2.5.0" id("org.jetbrains.intellij.platform") version "2.5.0"
id("org.jetbrains.changelog") version "2.2.1" id("org.jetbrains.changelog") version "2.2.1"
id("org.jetbrains.grammarkit") version "2022.3.2.2" apply false id("org.jetbrains.grammarkit") version "2022.3.2.2" apply false
idea idea
`maven-publish` `maven-publish`
} }
val publishVersions = listOf("241", "242", "243") val publishVersions = listOf("241", "242", "243", "251")
val pluginVersionFull get() = "$pluginVersion-$pluginSinceBuild" val pluginVersionFull get() = "$pluginVersion-$pluginSinceBuild"
val pluginVersion: String by project val pluginVersion: String by project
val pluginSinceBuild: String by project val pluginSinceBuild: String by project

View file

@ -23,7 +23,7 @@
set -e set -e
declare -a branches=("master" "242" "241") declare -a branches=("master" "243" "242" "241")
DEFAULT_BRANCH="${branches[0]}" DEFAULT_BRANCH="${branches[0]}"

View file

@ -14,6 +14,8 @@ sourceSets["main"].resources.srcDir(genOutputDir)
tasks { tasks {
register<Download>("downloadProps") { register<Download>("downloadProps") {
onlyIfModified(true)
useETag(true)
src("https://falsepattern.com/zigbrains/msvc.properties") src("https://falsepattern.com/zigbrains/msvc.properties")
dest(genOutputDir.map { it.file("msvc.properties") }) dest(genOutputDir.map { it.file("msvc.properties") })
} }

View file

@ -58,7 +58,8 @@ class ZigClionDebuggerDriverConfigurationProvider: ZigDebuggerDriverConfiguratio
return when(toolchain.debuggerKind) { return when(toolchain.debuggerKind) {
CPPDebugger.Kind.BUNDLED_GDB, CPPDebugger.Kind.BUNDLED_GDB,
CPPDebugger.Kind.CUSTOM_GDB -> CLionGDBDriverConfiguration(project, toolchain, isEmulateTerminal = emulateTerminal) CPPDebugger.Kind.CUSTOM_GDB -> CLionGDBDriverConfiguration(project, toolchain, isEmulateTerminal = emulateTerminal)
CPPDebugger.Kind.BUNDLED_LLDB -> CLionLLDBDriverConfiguration(project, toolchain, isEmulateTerminal = emulateTerminal) CPPDebugger.Kind.BUNDLED_LLDB,
CPPDebugger.Kind.CUSTOM_LLDB -> CLionLLDBDriverConfiguration(project, toolchain, isEmulateTerminal = emulateTerminal)
} }
} }
} }

View file

@ -24,8 +24,6 @@ package com.falsepattern.zigbrains.debugger.runner.base
import com.falsepattern.zigbrains.project.run.ZigProcessHandler import com.falsepattern.zigbrains.project.run.ZigProcessHandler
import com.falsepattern.zigbrains.shared.cli.startIPCAwareProcess import com.falsepattern.zigbrains.shared.cli.startIPCAwareProcess
import com.falsepattern.zigbrains.shared.ipc.IPCUtil
import com.falsepattern.zigbrains.shared.ipc.ipc
import com.intellij.execution.ExecutionException import com.intellij.execution.ExecutionException
import com.intellij.execution.configurations.GeneralCommandLine import com.intellij.execution.configurations.GeneralCommandLine
import com.intellij.execution.process.ProcessEvent import com.intellij.execution.process.ProcessEvent
@ -43,7 +41,7 @@ import kotlinx.coroutines.withContext
class PreLaunchProcessListener(val console: ConsoleView) : ProcessListener { class PreLaunchProcessListener(val console: ConsoleView) : ProcessListener {
var isBuildFailed: Boolean = false var isBuildFailed: Boolean = false
private set private set
lateinit var processHandler: ProcessHandler lateinit var processHandler: ZigProcessHandler.IPCAware
private set private set
@Throws(ExecutionException::class) @Throws(ExecutionException::class)
@ -53,7 +51,7 @@ class PreLaunchProcessListener(val console: ConsoleView) : ProcessListener {
this@PreLaunchProcessListener.processHandler = processHandler this@PreLaunchProcessListener.processHandler = processHandler
hook(processHandler) hook(processHandler)
processHandler.startNotify() processHandler.startNotify()
withContext(Dispatchers.Default) { withContext(Dispatchers.IO) {
processHandler.process.awaitExit() processHandler.process.awaitExit()
} }
runInterruptible { runInterruptible {

View file

@ -27,6 +27,7 @@ import com.falsepattern.zigbrains.project.execution.base.ZigProfileState
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
import com.intellij.execution.ExecutionException import com.intellij.execution.ExecutionException
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.toNioPathOrNull
import com.intellij.platform.util.progress.withProgressText import com.intellij.platform.util.progress.withProgressText
import com.intellij.util.containers.orNull import com.intellij.util.containers.orNull
import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration import com.jetbrains.cidr.execution.debugger.backend.DebuggerDriverConfiguration
@ -36,6 +37,7 @@ import java.io.File
import java.nio.file.Files import java.nio.file.Files
import kotlin.io.path.absolutePathString import kotlin.io.path.absolutePathString
import kotlin.io.path.isExecutable import kotlin.io.path.isExecutable
import kotlin.io.path.pathString
abstract class ZigDebugParametersEmitBinaryBase<ProfileState: ZigProfileState<*>>( abstract class ZigDebugParametersEmitBinaryBase<ProfileState: ZigProfileState<*>>(
driverConfiguration: DebuggerDriverConfiguration, driverConfiguration: DebuggerDriverConfiguration,
@ -49,13 +51,14 @@ abstract class ZigDebugParametersEmitBinaryBase<ProfileState: ZigProfileState<*>
@Throws(ExecutionException::class) @Throws(ExecutionException::class)
private suspend fun compileExe(listener: PreLaunchProcessListener): File { private suspend fun compileExe(listener: PreLaunchProcessListener): File {
val commandLine = profileState.getCommandLine(toolchain, true) val commandLine = profileState.getCommandLine(toolchain, true)
val cliString = commandLine.getCommandLineString(commandLine.exePath.toNioPathOrNull()?.fileName?.pathString)
val tmpDir = FileUtil.createTempDirectory("zigbrains_debug", "", true).toPath() val tmpDir = FileUtil.createTempDirectory("zigbrains_debug", "", true).toPath()
val exe = tmpDir.resolve("executable") val exe = tmpDir.resolve("executable")
commandLine.addParameters("-femit-bin=${exe.absolutePathString()}") commandLine.addParameters("-femit-bin=${exe.absolutePathString()}")
if (listener.executeCommandLineWithHook(profileState.environment.project, commandLine)) if (listener.executeCommandLineWithHook(profileState.environment.project, commandLine))
throw ExecutionException(ZigDebugBundle.message("debug.base.compile.failed.generic")) throw ExecutionException(ZigDebugBundle.message("debug.base.compile.failed.generic", cliString))
return withContext(Dispatchers.IO) { return withContext(Dispatchers.IO) {
Files.list(tmpDir).use { stream -> Files.list(tmpDir).use { stream ->

View file

@ -24,6 +24,7 @@ package com.falsepattern.zigbrains.debugger.runner.base
import com.falsepattern.zigbrains.debugbridge.ZigDebuggerDriverConfigurationProviderBase import com.falsepattern.zigbrains.debugbridge.ZigDebuggerDriverConfigurationProviderBase
import com.falsepattern.zigbrains.debugger.ZigLocalDebugProcess import com.falsepattern.zigbrains.debugger.ZigLocalDebugProcess
import com.falsepattern.zigbrains.debugger.runner.build.ZigDebugRunnerBuild
import com.falsepattern.zigbrains.project.execution.base.ZigProfileState import com.falsepattern.zigbrains.project.execution.base.ZigProfileState
import com.falsepattern.zigbrains.project.run.ZigProgramRunner import com.falsepattern.zigbrains.project.run.ZigProgramRunner
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
@ -41,6 +42,7 @@ import com.intellij.execution.ui.ConsoleView
import com.intellij.execution.ui.ConsoleViewContentType import com.intellij.execution.ui.ConsoleViewContentType
import com.intellij.execution.ui.RunContentDescriptor import com.intellij.execution.ui.RunContentDescriptor
import com.intellij.openapi.application.ModalityState import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.project.guessProjectDir
import com.intellij.platform.util.progress.reportProgress import com.intellij.platform.util.progress.reportProgress
import com.intellij.xdebugger.XDebugProcess import com.intellij.xdebugger.XDebugProcess
import com.intellij.xdebugger.XDebugProcessStarter import com.intellij.xdebugger.XDebugProcessStarter
@ -82,11 +84,13 @@ abstract class ZigDebugRunnerBase<ProfileState : ZigProfileState<*>> : ZigProgra
} }
} catch (e: ExecutionException) { } catch (e: ExecutionException) {
console.print("\n", ConsoleViewContentType.ERROR_OUTPUT) console.print("\n", ConsoleViewContentType.ERROR_OUTPUT)
e.message?.let { listener.console.print(it, ConsoleViewContentType.SYSTEM_OUTPUT) } e.message?.let { listener.console.print(it, ConsoleViewContentType.ERROR_OUTPUT) }
throw e; if (this !is ZigDebugRunnerBuild && environment.project.guessProjectDir()?.children?.any { it.name == "build.zig" } == true) {
console.print("\n Warning: build.zig file detected in project.\n Did you want to use a Zig Build task instead?", ConsoleViewContentType.ERROR_OUTPUT)
}
} }
if (listener.isBuildFailed) { if (listener.isBuildFailed) {
val executionResult = DefaultExecutionResult(console, listener.processHandler) val executionResult = DefaultExecutionResult(console, listener.processHandler.unwrap())
return@reportProgress withEDTContext(ModalityState.any()) { return@reportProgress withEDTContext(ModalityState.any()) {
val runContentBuilder = RunContentBuilder(executionResult, environment) val runContentBuilder = RunContentBuilder(executionResult, environment)
runContentBuilder.showRunContent(null) runContentBuilder.showRunContent(null)

View file

@ -48,7 +48,6 @@ import com.jetbrains.cidr.execution.debugger.CidrDebuggerPathManager
import com.jetbrains.cidr.execution.debugger.backend.bin.UrlProvider import com.jetbrains.cidr.execution.debugger.backend.bin.UrlProvider
import com.jetbrains.cidr.execution.debugger.backend.lldb.LLDBDriverConfiguration import com.jetbrains.cidr.execution.debugger.backend.lldb.LLDBDriverConfiguration
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runInterruptible
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.io.IOException import java.io.IOException
import java.net.URL import java.net.URL

View file

@ -15,7 +15,7 @@ debugger.run.unavailable.reason.download.button=Download
debugger.run.unavailable.reason.update=Debugger is outdated debugger.run.unavailable.reason.update=Debugger is outdated
debugger.run.unavailable.reason.update.button=Update debugger.run.unavailable.reason.update.button=Update
debug.build.compile.failed.boilerplate={0}\nPlease edit this intellij build configuration and specify the path of the executable created by "zig build" directly! debug.build.compile.failed.boilerplate={0}\nPlease edit this intellij build configuration and specify the path of the executable created by "zig build" directly!
debug.base.compile.failed.generic=Failed to compile executable debug.base.compile.failed.generic=Failed to compile executable with command: {0}
debug.base.compile.failed.no-exe=Failed to find compiled binary debug.base.compile.failed.no-exe=Failed to find compiled binary
debug.build.compile.failed.multiple-exe=Multiple compiled binaries found debug.build.compile.failed.multiple-exe=Multiple compiled binaries found
debug.build.compile.failed.no-workdir=Cannot find working directory to run debugged executable debug.build.compile.failed.no-workdir=Cannot find working directory to run debugged executable

View file

@ -9,12 +9,15 @@ plugins {
val ideaCommunityVersion: String by project val ideaCommunityVersion: String by project
val useInstaller = property("useInstaller").toString().toBoolean() val useInstaller = property("useInstaller").toString().toBoolean()
val serializationVersion: String by project
dependencies { dependencies {
intellijPlatform { intellijPlatform {
create(IntelliJPlatformType.IntellijIdeaCommunity, ideaCommunityVersion, useInstaller = useInstaller) create(IntelliJPlatformType.IntellijIdeaCommunity, ideaCommunityVersion, useInstaller = useInstaller)
} }
compileOnly("org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3") compileOnly("org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:$serializationVersion") {
isTransitive = false
}
} }
//region grammars //region grammars

View file

@ -26,7 +26,6 @@ import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.io.toNioPathOrNull import com.intellij.openapi.util.io.toNioPathOrNull
import com.intellij.util.EnvironmentUtil import com.intellij.util.EnvironmentUtil
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.firstOrNull
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.flow.flowOn
import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.NonNls

View file

@ -26,7 +26,6 @@ import com.intellij.execution.filters.TextConsoleBuilderImpl
import com.intellij.execution.ui.ConsoleView import com.intellij.execution.ui.ConsoleView
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.terminal.TerminalExecutionConsole import com.intellij.terminal.TerminalExecutionConsole
import java.nio.file.Path
class ZigConsoleBuilder(private val project: Project, private val emulateTerminal: Boolean = false): TextConsoleBuilderImpl(project) { class ZigConsoleBuilder(private val project: Project, private val emulateTerminal: Boolean = false): TextConsoleBuilderImpl(project) {
override fun createConsole(): ConsoleView { override fun createConsole(): ConsoleView {

View file

@ -35,8 +35,6 @@ import com.intellij.execution.configurations.PtyCommandLine
import com.intellij.execution.process.ProcessHandler import com.intellij.execution.process.ProcessHandler
import com.intellij.execution.runners.ExecutionEnvironment import com.intellij.execution.runners.ExecutionEnvironment
import com.intellij.platform.ide.progress.ModalTaskOwner import com.intellij.platform.ide.progress.ModalTaskOwner
import com.intellij.platform.util.progress.reportProgress
import com.intellij.platform.util.progress.reportRawProgress
import kotlin.io.path.pathString import kotlin.io.path.pathString
abstract class ZigProfileState<T: ZigExecConfig<T>> ( abstract class ZigProfileState<T: ZigExecConfig<T>> (

View file

@ -0,0 +1,56 @@
/*
* 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.execution.base
import com.falsepattern.zigbrains.zig.psi.ZigContainerMembers
import com.falsepattern.zigbrains.zig.psi.ZigFile
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.isFile
import com.intellij.psi.util.childrenOfType
fun ZigFile.hasMainFunction(): Boolean {
val members = childrenOfType<ZigContainerMembers>().firstOrNull() ?: return false
return members.containerDeclarationList.any { it.decl?.fnProto?.identifier?.textMatches("main") == true }
}
fun ZigFile.hasTests(): Boolean {
val members = childrenOfType<ZigContainerMembers>().firstOrNull() ?: return false
return members.containerDeclarationList.any { it.testDecl != null }
}
fun VirtualFile.findBuildZig(): VirtualFile? {
var parent = this.parent
while (parent != null) {
parent.children.forEach {
if (it.isFile && it.name == "build.zig") {
return it
}
}
parent = parent.parent
}
return null
}
fun VirtualFile.isBuildZig(): Boolean {
return name == "build.zig"
}

View file

@ -24,12 +24,16 @@ 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.base.findBuildZig
import com.falsepattern.zigbrains.project.execution.base.isBuildZig
import com.falsepattern.zigbrains.project.execution.firstConfigFactory import com.falsepattern.zigbrains.project.execution.firstConfigFactory
import com.falsepattern.zigbrains.zig.psi.ZigFile import com.falsepattern.zigbrains.zig.psi.ZigFile
import com.falsepattern.zigbrains.zig.psi.ZigTypes
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.elementType
import java.nio.file.Path import java.nio.file.Path
class ZigConfigProducerBuild: ZigConfigProducer<ZigExecConfigBuild>() { class ZigConfigProducerBuild: ZigConfigProducer<ZigExecConfigBuild>() {
@ -38,14 +42,39 @@ class ZigConfigProducerBuild: ZigConfigProducer<ZigExecConfigBuild>() {
} }
override fun setupConfigurationFromContext(configuration: ZigExecConfigBuild, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean { override fun setupConfigurationFromContext(configuration: ZigExecConfigBuild, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean {
if (theFile.name != "build.zig") if (theFile.isBuildZig()) {
return false configuration.name = ZigBrainsBundle.message("configuration.build.marker-run")
configuration.name = ZigBrainsBundle.message("configuration.build.marker-name") configuration.buildSteps.args = "run"
configuration.debugBuildSteps.args = "install"
return true return true
} }
val buildZig = theFile.findBuildZig() ?: return false
configuration.workingDirectory.path = buildZig.parent.toNioPath()
if (element.elementType == ZigTypes.KEYWORD_TEST) {
configuration.name = ZigBrainsBundle.message("configuration.build.marker-test")
configuration.buildSteps.args = "test"
configuration.debugBuildSteps.args = "install_test"
return true
} else {
configuration.name = ZigBrainsBundle.message("configuration.build.marker-run")
configuration.buildSteps.args = "run"
configuration.debugBuildSteps.args = "install"
return true
}
}
override fun isConfigurationFromContext(configuration: ZigExecConfigBuild, element: PsiElement, psiFile: ZigFile, 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) val dir = configuration.workingDirectory.path ?: return false
if (theFile.isBuildZig()) {
return filePath.parent == dir
} else {
if (element.elementType == ZigTypes.KEYWORD_TEST) {
if (configuration.buildSteps.args != "test")
return false
}
val buildZig = theFile.findBuildZig() ?: return false
return buildZig.parent.toNioPath() == dir
}
} }
override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean { override fun shouldReplace(self: ConfigurationFromContext, other: ConfigurationFromContext): Boolean {

View file

@ -23,14 +23,14 @@
package com.falsepattern.zigbrains.project.execution.run 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.base.findBuildZig
import com.falsepattern.zigbrains.project.execution.base.hasMainFunction
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.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>() {
@ -39,8 +39,10 @@ class ZigConfigProducerRun: ZigConfigProducer<ZigExecConfigRun>() {
} }
override fun setupConfigurationFromContext(configuration: ZigExecConfigRun, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean { override fun setupConfigurationFromContext(configuration: ZigExecConfigRun, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean {
val members = psiFile.childrenOfType<ZigContainerMembers>().firstOrNull() ?: return false if (!psiFile.hasMainFunction()) {
if (members.containerDeclarationList.none { it.decl?.fnProto?.identifier?.textMatches("main") == true }) { return false
}
if (theFile.findBuildZig() != null) {
return false return false
} }
configuration.filePath.path = filePath configuration.filePath.path = filePath
@ -56,5 +58,3 @@ class ZigConfigProducerRun: ZigConfigProducer<ZigExecConfigRun>() {
return self.configurationType is ZigConfigTypeRun return self.configurationType is ZigConfigTypeRun
} }
} }
private val LINE_MARKER = ZigLineMarkerRun()

View file

@ -24,14 +24,14 @@ 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.base.findBuildZig
import com.falsepattern.zigbrains.project.execution.base.hasTests
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.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>() {
@ -40,8 +40,10 @@ class ZigConfigProducerTest: ZigConfigProducer<ZigExecConfigTest>() {
} }
override fun setupConfigurationFromContext(configuration: ZigExecConfigTest, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean { override fun setupConfigurationFromContext(configuration: ZigExecConfigTest, element: PsiElement, psiFile: ZigFile, filePath: Path, theFile: VirtualFile): Boolean {
val members = psiFile.childrenOfType<ZigContainerMembers>().firstOrNull() ?: return false if (!psiFile.hasTests()) {
if (members.containerDeclarationList.none { it.testDecl != null }) { return false
}
if (theFile.findBuildZig() != null) {
return false return false
} }
configuration.filePath.path = filePath configuration.filePath.path = filePath

View file

@ -23,10 +23,8 @@
package com.falsepattern.zigbrains.project.newproject package com.falsepattern.zigbrains.project.newproject
import com.intellij.ide.util.projectWizard.SettingsStep import com.intellij.ide.util.projectWizard.SettingsStep
import com.intellij.openapi.Disposable
import com.intellij.openapi.ui.TextFieldWithBrowseButton import com.intellij.openapi.ui.TextFieldWithBrowseButton
import com.intellij.openapi.ui.ValidationInfo import com.intellij.openapi.ui.ValidationInfo
import com.intellij.openapi.util.Disposer
import com.intellij.platform.ProjectGeneratorPeer import com.intellij.platform.ProjectGeneratorPeer
import com.intellij.ui.dsl.builder.panel import com.intellij.ui.dsl.builder.panel
import javax.swing.JComponent import javax.swing.JComponent

View file

@ -24,21 +24,29 @@ package com.falsepattern.zigbrains.project.run
import com.intellij.execution.configurations.GeneralCommandLine import com.intellij.execution.configurations.GeneralCommandLine
import com.intellij.execution.configurations.PtyCommandLine import com.intellij.execution.configurations.PtyCommandLine
import com.intellij.execution.process.AnsiEscapeDecoder.ColoredTextAcceptor
import com.intellij.execution.process.KillableColoredProcessHandler
import com.intellij.execution.process.KillableProcessHandler import com.intellij.execution.process.KillableProcessHandler
import com.intellij.openapi.util.Key
import com.pty4j.PtyProcess import com.pty4j.PtyProcess
import java.nio.charset.Charset import java.nio.charset.Charset
class ZigProcessHandler : KillableProcessHandler { open class ZigProcessHandler : KillableProcessHandler {
constructor(commandLine: GeneralCommandLine) : super(commandLine) { constructor(commandLine: GeneralCommandLine) : super(commandLine) {
setHasPty(commandLine is PtyCommandLine) setHasPty(commandLine is PtyCommandLine)
setShouldDestroyProcessRecursively(!hasPty()) setShouldDestroyProcessRecursively(!hasPty())
} }
constructor (process: Process, commandLine: String, charset: Charset) : super(process, commandLine, charset) { protected constructor (process: Process, commandLine: String, charset: Charset) : super(process, commandLine, charset) {
setHasPty(process is PtyProcess) setHasPty(process is PtyProcess)
setShouldDestroyProcessRecursively(!hasPty()) setShouldDestroyProcessRecursively(!hasPty())
} }
class IPCAware : ZigProcessHandler {
val originalCommandLine: String
constructor(originalCommandLine: String, commandLine: GeneralCommandLine) : super(commandLine) {
this.originalCommandLine = originalCommandLine
}
fun unwrap(): ZigProcessHandler {
return ZigProcessHandler(this.process, this.originalCommandLine, this.charset ?: Charsets.UTF_8)
}
}
} }

View file

@ -75,16 +75,40 @@ class ZigSyntheticLibrary(val project: Project) : SyntheticLibrary(), ItemPresen
return roots return roots
} }
override fun isShowInExternalLibrariesNode(): Boolean {
return !roots.isEmpty()
}
companion object { companion object {
private const val ZIG_LIBRARY_ID = "Zig SDK" private const val ZIG_LIBRARY_ID = "Zig SDK"
private const val ZIG_MODULE_ID = "ZigBrains" private const val ZIG_MODULE_ID = "ZigBrains"
private val libraryTableId = LibraryTableId.ProjectLibraryTableId
private val libraryId = LibraryId(ZIG_LIBRARY_ID, libraryTableId)
private val moduleId = ModuleId(ZIG_MODULE_ID)
suspend fun reload(project: Project, toolchain: ZigToolchain?) { suspend fun reload(project: Project, toolchain: ZigToolchain?) {
val moduleId = ModuleId(ZIG_MODULE_ID) val root = getRoot(toolchain, project)
if (root != null) {
add(project, root)
} else {
remove(project)
}
}
private suspend fun remove(project: Project) {
val workspaceModel = WorkspaceModel.getInstance(project)
workspaceModel.update("Update Zig std") { builder ->
builder.resolve(moduleId)?.let { moduleEntity ->
builder.removeEntity(moduleEntity)
}
builder.resolve(libraryId)?.let { libraryEntity ->
builder.removeEntity(libraryEntity)
}
}
}
private suspend fun add(project: Project, root: VirtualFile) {
val workspaceModel = WorkspaceModel.getInstance(project) val workspaceModel = WorkspaceModel.getInstance(project)
val root = getRoot(toolchain, project) ?: return
val libRoot = LibraryRoot(root.toVirtualFileUrl(workspaceModel.getVirtualFileUrlManager()), LibraryRootTypeId.SOURCES) val libRoot = LibraryRoot(root.toVirtualFileUrl(workspaceModel.getVirtualFileUrlManager()), LibraryRootTypeId.SOURCES)
val libraryTableId = LibraryTableId.ProjectLibraryTableId
val libraryId = LibraryId(ZIG_LIBRARY_ID, libraryTableId)
var baseModuleDirFile: VirtualFile? = null var baseModuleDirFile: VirtualFile? = null
if (project.isDirectoryBased) { if (project.isDirectoryBased) {

View file

@ -28,7 +28,10 @@ import com.falsepattern.zigbrains.project.toolchain.base.resolve
import com.falsepattern.zigbrains.project.toolchain.base.toRef import com.falsepattern.zigbrains.project.toolchain.base.toRef
import com.falsepattern.zigbrains.shared.UUIDMapSerializable import com.falsepattern.zigbrains.shared.UUIDMapSerializable
import com.falsepattern.zigbrains.shared.UUIDStorage import com.falsepattern.zigbrains.shared.UUIDStorage
import com.intellij.openapi.components.* import com.intellij.openapi.components.Service
import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage
import com.intellij.openapi.components.service
@Service(Service.Level.APP) @Service(Service.Level.APP)
@State( @State(

View file

@ -27,16 +27,12 @@ import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
import com.falsepattern.zigbrains.shared.asUUID import com.falsepattern.zigbrains.shared.asUUID
import com.falsepattern.zigbrains.shared.zigCoroutineScope import com.falsepattern.zigbrains.shared.zigCoroutineScope
import com.intellij.openapi.application.EDT import com.intellij.openapi.application.EDT
import com.intellij.openapi.components.SerializablePersistentStateComponent import com.intellij.openapi.components.*
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage
import com.intellij.openapi.components.service
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.util.xmlb.annotations.Attribute import com.intellij.util.xmlb.annotations.Attribute
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.UUID import java.util.*
@Service(Service.Level.PROJECT) @Service(Service.Level.PROJECT)
@State( @State(

View file

@ -26,9 +26,7 @@ import com.falsepattern.zigbrains.project.toolchain.tools.ZigCompilerTool
import com.falsepattern.zigbrains.shared.NamedObject import com.falsepattern.zigbrains.shared.NamedObject
import com.intellij.execution.configurations.GeneralCommandLine import com.intellij.execution.configurations.GeneralCommandLine
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.util.Key
import com.intellij.util.xmlb.annotations.Attribute import com.intellij.util.xmlb.annotations.Attribute
import com.intellij.util.xmlb.annotations.MapAnnotation
import java.nio.file.Path import java.nio.file.Path
/** /**

View file

@ -25,12 +25,12 @@ package com.falsepattern.zigbrains.project.toolchain.base
import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider
import com.falsepattern.zigbrains.project.toolchain.ui.ImmutableElementPanel import com.falsepattern.zigbrains.project.toolchain.ui.ImmutableElementPanel
import com.falsepattern.zigbrains.project.toolchain.zigToolchainList import com.falsepattern.zigbrains.project.toolchain.zigToolchainList
import com.intellij.openapi.project.Project import com.falsepattern.zigbrains.shared.ui.UUIDComboBoxDriver.Companion.wrapModal
import com.intellij.openapi.ui.NamedConfigurable import com.intellij.openapi.ui.NamedConfigurable
import com.intellij.openapi.util.Key import com.intellij.openapi.util.Key
import com.intellij.openapi.util.NlsContexts import com.intellij.openapi.util.NlsContexts
import com.intellij.ui.dsl.builder.panel import com.intellij.ui.dsl.builder.panel
import java.util.UUID import java.util.*
import java.util.function.Supplier import java.util.function.Supplier
import javax.swing.JComponent import javax.swing.JComponent
@ -38,7 +38,7 @@ abstract class ZigToolchainConfigurable<T: ZigToolchain>(
val uuid: UUID, val uuid: UUID,
tc: T, tc: T,
val data: ZigProjectConfigurationProvider.IUserDataBridge?, val data: ZigProjectConfigurationProvider.IUserDataBridge?,
val modal: Boolean private val modal: Boolean
): NamedConfigurable<UUID>() { ): NamedConfigurable<UUID>() {
var toolchain: T = tc var toolchain: T = tc
set(value) { set(value) {
@ -65,7 +65,7 @@ abstract class ZigToolchainConfigurable<T: ZigToolchain>(
views.forEach { it.attach(this@panel) } views.forEach { it.attach(this@panel) }
}.withMinimumWidth(20) }.withMinimumWidth(20)
views.forEach { it.reset(toolchain) } views.forEach { it.reset(toolchain) }
return p return wrapModal(p, modal)
} }
override fun getEditableObject(): UUID? { override fun getEditableObject(): UUID? {

View file

@ -31,13 +31,8 @@ import com.intellij.openapi.util.UserDataHolder
import com.intellij.ui.SimpleColoredComponent import com.intellij.ui.SimpleColoredComponent
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.asFlow import java.util.*
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.flowOn
import java.util.UUID
import kotlin.collections.none
private val EXTENSION_POINT_NAME = ExtensionPointName.create<ZigToolchainProvider>("com.falsepattern.zigbrains.toolchainProvider") private val EXTENSION_POINT_NAME = ExtensionPointName.create<ZigToolchainProvider>("com.falsepattern.zigbrains.toolchainProvider")

View file

@ -24,18 +24,15 @@ package com.falsepattern.zigbrains.project.toolchain.downloader
import com.falsepattern.zigbrains.ZigBrainsBundle import com.falsepattern.zigbrains.ZigBrainsBundle
import com.falsepattern.zigbrains.project.toolchain.local.LocalZigToolchain import com.falsepattern.zigbrains.project.toolchain.local.LocalZigToolchain
import com.falsepattern.zigbrains.project.toolchain.local.getSuggestedLocalToolchainPath import com.falsepattern.zigbrains.project.toolchain.local.suggestedLocalToolchainPath
import com.falsepattern.zigbrains.shared.downloader.Downloader import com.falsepattern.zigbrains.shared.downloader.Downloader
import com.falsepattern.zigbrains.shared.downloader.LocalSelector
import com.intellij.openapi.util.NlsContexts
import java.awt.Component import java.awt.Component
import java.nio.file.Path
class LocalToolchainDownloader(component: Component) : Downloader<LocalZigToolchain, ZigVersionInfo>(component) { class LocalToolchainDownloader(component: Component) : Downloader<LocalZigToolchain, ZigVersionInfo>(component) {
override val windowTitle get() = ZigBrainsBundle.message("settings.toolchain.downloader.title") override val windowTitle get() = ZigBrainsBundle.message("settings.toolchain.downloader.title")
override val versionInfoFetchTitle get() = ZigBrainsBundle.message("settings.toolchain.downloader.progress.fetch") override val versionInfoFetchTitle get() = ZigBrainsBundle.message("settings.toolchain.downloader.progress.fetch")
override val suggestedPath get() = suggestedLocalToolchainPath
override fun downloadProgressTitle(version: ZigVersionInfo) = ZigBrainsBundle.message("settings.toolchain.downloader.progress.install", version.version.rawVersion) override fun downloadProgressTitle(version: ZigVersionInfo) = ZigBrainsBundle.message("settings.toolchain.downloader.progress.install", version.version.rawVersion)
override fun localSelector() = LocalToolchainSelector(component) override fun localSelector() = LocalToolchainSelector(component)
override suspend fun downloadVersionList() = ZigVersionInfo.downloadVersionList() override suspend fun downloadVersionList() = ZigVersionInfo.downloadVersionList()
override fun getSuggestedPath() = getSuggestedLocalToolchainPath()
} }

View file

@ -23,37 +23,18 @@
package com.falsepattern.zigbrains.project.toolchain.downloader package com.falsepattern.zigbrains.project.toolchain.downloader
import com.falsepattern.zigbrains.ZigBrainsBundle import com.falsepattern.zigbrains.ZigBrainsBundle
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
import com.falsepattern.zigbrains.project.toolchain.local.LocalZigToolchain import com.falsepattern.zigbrains.project.toolchain.local.LocalZigToolchain
import com.falsepattern.zigbrains.project.toolchain.zigToolchainList import com.falsepattern.zigbrains.project.toolchain.zigToolchainList
import com.falsepattern.zigbrains.shared.coroutine.asContextElement
import com.falsepattern.zigbrains.shared.coroutine.launchWithEDT
import com.falsepattern.zigbrains.shared.coroutine.withEDTContext
import com.falsepattern.zigbrains.shared.downloader.LocalSelector import com.falsepattern.zigbrains.shared.downloader.LocalSelector
import com.falsepattern.zigbrains.shared.withUniqueName import com.falsepattern.zigbrains.shared.withUniqueName
import com.falsepattern.zigbrains.shared.zigCoroutineScope
import com.intellij.icons.AllIcons import com.intellij.icons.AllIcons
import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.fileChooser.FileChooser
import com.intellij.openapi.fileChooser.FileChooserDescriptor import com.intellij.openapi.fileChooser.FileChooserDescriptor
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
import com.intellij.openapi.ui.DialogBuilder
import com.intellij.openapi.util.Disposer
import com.intellij.platform.ide.progress.ModalTaskOwner import com.intellij.platform.ide.progress.ModalTaskOwner
import com.intellij.platform.ide.progress.TaskCancellation import com.intellij.platform.ide.progress.TaskCancellation
import com.intellij.platform.ide.progress.withModalProgress import com.intellij.platform.ide.progress.withModalProgress
import com.intellij.ui.DocumentAdapter
import com.intellij.ui.components.JBLabel
import com.intellij.ui.components.JBTextField
import com.intellij.ui.components.textFieldWithBrowseButton
import com.intellij.ui.dsl.builder.AlignX
import com.intellij.ui.dsl.builder.panel
import com.intellij.util.concurrency.annotations.RequiresEdt
import java.awt.Component import java.awt.Component
import java.nio.file.Path import java.nio.file.Path
import java.util.concurrent.atomic.AtomicBoolean
import javax.swing.event.DocumentEvent
import kotlin.io.path.pathString
class LocalToolchainSelector(component: Component): LocalSelector<LocalZigToolchain>(component) { class LocalToolchainSelector(component: Component): LocalSelector<LocalZigToolchain>(component) {
override val windowTitle: String override val windowTitle: String

View file

@ -23,46 +23,19 @@
package com.falsepattern.zigbrains.project.toolchain.downloader package com.falsepattern.zigbrains.project.toolchain.downloader
import com.falsepattern.zigbrains.ZigBrainsBundle import com.falsepattern.zigbrains.ZigBrainsBundle
import com.falsepattern.zigbrains.shared.Unarchiver
import com.falsepattern.zigbrains.shared.downloader.VersionInfo import com.falsepattern.zigbrains.shared.downloader.VersionInfo
import com.falsepattern.zigbrains.shared.downloader.VersionInfo.Tarball import com.falsepattern.zigbrains.shared.downloader.VersionInfo.Tarball
import com.falsepattern.zigbrains.shared.downloader.downloadTarball
import com.falsepattern.zigbrains.shared.downloader.flattenDownloadDir
import com.falsepattern.zigbrains.shared.downloader.getTarballIfCompatible import com.falsepattern.zigbrains.shared.downloader.getTarballIfCompatible
import com.falsepattern.zigbrains.shared.downloader.tempPluginDir import com.falsepattern.zigbrains.shared.downloader.tempPluginDir
import com.falsepattern.zigbrains.shared.downloader.unpackTarball
import com.intellij.openapi.application.PathManager
import com.intellij.openapi.progress.EmptyProgressIndicator
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.progress.coroutineToIndicator import com.intellij.openapi.progress.coroutineToIndicator
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.toNioPathOrNull
import com.intellij.platform.util.progress.*
import com.intellij.util.asSafely import com.intellij.util.asSafely
import com.intellij.util.download.DownloadableFileService import com.intellij.util.download.DownloadableFileService
import com.intellij.util.io.createDirectories
import com.intellij.util.io.delete
import com.intellij.util.io.move
import com.intellij.util.system.CpuArch
import com.intellij.util.system.OS
import com.intellij.util.text.SemVer import com.intellij.util.text.SemVer
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.Serializable import kotlinx.serialization.json.*
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.decodeFromStream
import java.io.File
import java.nio.file.Files
import java.nio.file.Path
import kotlin.io.path.ExperimentalPathApi
import kotlin.io.path.deleteRecursively
import kotlin.io.path.isDirectory
import kotlin.io.path.name
@JvmRecord @JvmRecord
data class ZigVersionInfo( data class ZigVersionInfo(

View file

@ -28,11 +28,8 @@ import com.intellij.execution.ExecutionException
import com.intellij.execution.configurations.GeneralCommandLine import com.intellij.execution.configurations.GeneralCommandLine
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.project.guessProjectDir import com.intellij.openapi.project.guessProjectDir
import com.intellij.openapi.util.Key
import com.intellij.openapi.util.SystemInfo import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.io.toNioPathOrNull
import com.intellij.openapi.vfs.toNioPathOrNull import com.intellij.openapi.vfs.toNioPathOrNull
import com.intellij.util.keyFMap.KeyFMap
import java.nio.file.Path import java.nio.file.Path
@JvmRecord @JvmRecord

View file

@ -24,7 +24,7 @@ package com.falsepattern.zigbrains.project.toolchain.local
import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchainConfigurable import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchainConfigurable
import java.util.UUID import java.util.*
class LocalZigToolchainConfigurable( class LocalZigToolchainConfigurable(
uuid: UUID, uuid: UUID,

View file

@ -73,8 +73,8 @@ class LocalZigToolchainPanel() : ImmutableNamedElementPanelBase<LocalZigToolchai
).also { Disposer.register(this, it) } ).also { Disposer.register(this, it) }
private var debounce: Job? = null private var debounce: Job? = null
override fun attach(p: Panel): Unit = with(p) { override fun attach(panel: Panel): Unit = with(panel) {
super.attach(p) super.attach(panel)
row(ZigBrainsBundle.message("settings.toolchain.local.path.label")) { row(ZigBrainsBundle.message("settings.toolchain.local.path.label")) {
cell(pathToToolchain).resizableColumn().align(AlignX.FILL) cell(pathToToolchain).resizableColumn().align(AlignX.FILL)
} }
@ -87,23 +87,23 @@ class LocalZigToolchainPanel() : ImmutableNamedElementPanelBase<LocalZigToolchai
} }
} }
override fun isModified(toolchain: LocalZigToolchain): Boolean { override fun isModified(elem: LocalZigToolchain): Boolean {
val name = nameFieldValue ?: return false val name = nameFieldValue ?: return false
val location = this.pathToToolchain.text.ifBlank { null }?.toNioPathOrNull() ?: return false val location = this.pathToToolchain.text.ifBlank { null }?.toNioPathOrNull() ?: return false
val std = if (stdFieldOverride.isSelected) pathToStd.text.ifBlank { null }?.toNioPathOrNull() else null val std = if (stdFieldOverride.isSelected) pathToStd.text.ifBlank { null }?.toNioPathOrNull() else null
return name != toolchain.name || toolchain.location != location || toolchain.std != std return name != elem.name || elem.location != location || elem.std != std
} }
override fun apply(toolchain: LocalZigToolchain): LocalZigToolchain? { override fun apply(elem: LocalZigToolchain): LocalZigToolchain? {
val location = this.pathToToolchain.text.ifBlank { null }?.toNioPathOrNull() ?: return null val location = this.pathToToolchain.text.ifBlank { null }?.toNioPathOrNull() ?: return null
val std = if (stdFieldOverride.isSelected) pathToStd.text.ifBlank { null }?.toNioPathOrNull() else null val std = if (stdFieldOverride.isSelected) pathToStd.text.ifBlank { null }?.toNioPathOrNull() else null
return toolchain.copy(location = location, std = std, name = nameFieldValue ?: "") return elem.copy(location = location, std = std, name = nameFieldValue ?: "")
} }
override fun reset(toolchain: LocalZigToolchain?) { override fun reset(elem: LocalZigToolchain?) {
nameFieldValue = toolchain?.name ?: "" nameFieldValue = elem?.name ?: ""
this.pathToToolchain.text = toolchain?.location?.pathString ?: "" this.pathToToolchain.text = elem?.location?.pathString ?: ""
val std = toolchain?.std val std = elem?.std
if (std != null) { if (std != null) {
stdFieldOverride.isSelected = true stdFieldOverride.isSelected = true
pathToStd.text = std.pathString pathToStd.text = std.pathString

View file

@ -28,27 +28,18 @@ import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvid
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchainConfigurable import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchainConfigurable
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchainProvider import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchainProvider
import com.falsepattern.zigbrains.shared.downloader.homePath
import com.falsepattern.zigbrains.shared.downloader.xdgDataHome
import com.falsepattern.zigbrains.shared.ui.renderPathNameComponent import com.falsepattern.zigbrains.shared.ui.renderPathNameComponent
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.util.UserDataHolder import com.intellij.openapi.util.UserDataHolder
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.toNioPathOrNull import com.intellij.openapi.util.io.toNioPathOrNull
import com.intellij.openapi.util.text.StringUtil
import com.intellij.ui.SimpleColoredComponent import com.intellij.ui.SimpleColoredComponent
import com.intellij.ui.SimpleTextAttributes
import com.intellij.util.system.OS
import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.*
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.flow.flatMapConcat
import kotlinx.coroutines.flow.flattenConcat
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.mapNotNull
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
import java.util.UUID import java.util.*
import kotlin.io.path.isDirectory
import kotlin.io.path.pathString import kotlin.io.path.pathString
class LocalZigToolchainProvider: ZigToolchainProvider { class LocalZigToolchainProvider: ZigToolchainProvider {
@ -102,7 +93,7 @@ class LocalZigToolchainProvider: ZigToolchainProvider {
Env.empty Env.empty
} }
val pathToolchains = env.findAllExecutablesOnPATH("zig").mapNotNull { it.parent } val pathToolchains = env.findAllExecutablesOnPATH("zig").mapNotNull { it.parent }
val wellKnown = getWellKnown().asFlow().flatMapConcat { dir -> val wellKnown = wellKnown.asFlow().flatMapConcat { dir ->
runCatching { runCatching {
Files.newDirectoryStream(dir).use { stream -> Files.newDirectoryStream(dir).use { stream ->
stream.toList().filterNotNull().asFlow() stream.toList().filterNotNull().asFlow()
@ -121,8 +112,8 @@ class LocalZigToolchainProvider: ZigToolchainProvider {
} }
} }
fun getSuggestedLocalToolchainPath(): Path? { val suggestedLocalToolchainPath: Path? by lazy {
return getWellKnown().getOrNull(0) wellKnown.getOrNull(0)
} }
/** /**
@ -139,18 +130,12 @@ fun getSuggestedLocalToolchainPath(): Path? {
* *
* and HOME is the user home path * and HOME is the user home path
*/ */
private fun getWellKnown(): List<Path> { private val wellKnown: List<Path> by lazy {
val home = System.getProperty("user.home")?.toNioPathOrNull() ?: return emptyList()
val xdgDataHome = when(OS.CURRENT) {
OS.macOS -> home.resolve("Library")
OS.Windows -> System.getenv("LOCALAPPDATA")?.toNioPathOrNull()
else -> System.getenv("XDG_DATA_HOME")?.toNioPathOrNull() ?: home.resolve(Path.of(".local", "share"))
}
val res = ArrayList<Path>() val res = ArrayList<Path>()
if (xdgDataHome != null && xdgDataHome.isDirectory()) { xdgDataHome?.let {
res.add(xdgDataHome.resolve("zig")) res.add(it.resolve("zig"))
res.add(xdgDataHome.resolve("zigup")) res.add(it.resolve("zigup"))
} }
res.add(home.resolve(".zig")) homePath?.let { res.add(it.resolve(".zig")) }
return res res
} }

View file

@ -24,7 +24,6 @@ package com.falsepattern.zigbrains.project.toolchain.tools
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.SerializationException import kotlinx.serialization.SerializationException
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import java.nio.file.Path import java.nio.file.Path

View file

@ -26,7 +26,7 @@ import com.intellij.openapi.Disposable
import com.intellij.ui.dsl.builder.Panel import com.intellij.ui.dsl.builder.Panel
interface ImmutableElementPanel<T>: Disposable { interface ImmutableElementPanel<T>: Disposable {
fun attach(p: Panel) fun attach(panel: Panel)
fun isModified(elem: T): Boolean fun isModified(elem: T): Boolean
/** /**
* Returned object must be the exact same class as the provided one. * Returned object must be the exact same class as the provided one.

View file

@ -23,7 +23,6 @@
package com.falsepattern.zigbrains.project.toolchain.ui package com.falsepattern.zigbrains.project.toolchain.ui
import com.falsepattern.zigbrains.ZigBrainsBundle import com.falsepattern.zigbrains.ZigBrainsBundle
import com.falsepattern.zigbrains.shared.NamedObject
import com.intellij.ui.components.JBTextField import com.intellij.ui.components.JBTextField
import com.intellij.ui.dsl.builder.AlignX import com.intellij.ui.dsl.builder.AlignX
import com.intellij.ui.dsl.builder.Panel import com.intellij.ui.dsl.builder.Panel
@ -35,7 +34,7 @@ abstract class ImmutableNamedElementPanelBase<T>: ImmutableElementPanel<T> {
get() = nameField.text.ifBlank { null } get() = nameField.text.ifBlank { null }
set(value) {nameField.text = value ?: ""} set(value) {nameField.text = value ?: ""}
override fun attach(p: Panel): Unit = with(p) { override fun attach(panel: Panel): Unit = with(panel) {
row(ZigBrainsBundle.message("settings.toolchain.base.name.label")) { row(ZigBrainsBundle.message("settings.toolchain.base.name.label")) {
cell(nameField).resizableColumn().align(AlignX.FILL) cell(nameField).resizableColumn().align(AlignX.FILL)
} }

View file

@ -30,7 +30,7 @@ import com.falsepattern.zigbrains.shared.ui.ListElem
import com.falsepattern.zigbrains.shared.withUniqueName import com.falsepattern.zigbrains.shared.withUniqueName
import com.intellij.util.concurrency.annotations.RequiresBackgroundThread import com.intellij.util.concurrency.annotations.RequiresBackgroundThread
import java.awt.Component import java.awt.Component
import java.util.UUID import java.util.*
internal object ZigToolchainComboBoxHandler { internal object ZigToolchainComboBoxHandler {
@RequiresBackgroundThread @RequiresBackgroundThread

View file

@ -29,20 +29,10 @@ import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
import com.falsepattern.zigbrains.project.toolchain.base.createNamedConfigurable import com.falsepattern.zigbrains.project.toolchain.base.createNamedConfigurable
import com.falsepattern.zigbrains.project.toolchain.base.suggestZigToolchains import com.falsepattern.zigbrains.project.toolchain.base.suggestZigToolchains
import com.falsepattern.zigbrains.project.toolchain.zigToolchainList import com.falsepattern.zigbrains.project.toolchain.zigToolchainList
import com.falsepattern.zigbrains.shared.ui.ListElem import com.falsepattern.zigbrains.shared.ui.*
import com.falsepattern.zigbrains.shared.ui.ListElemIn
import com.falsepattern.zigbrains.shared.ui.Separator
import com.falsepattern.zigbrains.shared.ui.UUIDComboBoxDriver
import com.falsepattern.zigbrains.shared.ui.ZBComboBox
import com.falsepattern.zigbrains.shared.ui.ZBContext
import com.falsepattern.zigbrains.shared.ui.ZBModel
import com.falsepattern.zigbrains.shared.ui.asActual
import com.falsepattern.zigbrains.shared.ui.asPending
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.NamedConfigurable import com.intellij.openapi.ui.NamedConfigurable
import com.intellij.openapi.util.UserDataHolder
import java.awt.Component import java.awt.Component
import java.util.UUID import java.util.*
sealed interface ZigToolchainDriver: UUIDComboBoxDriver<ZigToolchain> { sealed interface ZigToolchainDriver: UUIDComboBoxDriver<ZigToolchain> {
override val theMap get() = zigToolchainList override val theMap get() = zigToolchainList

View file

@ -39,7 +39,7 @@ import com.intellij.openapi.project.ProjectManager
import com.intellij.openapi.util.Key import com.intellij.openapi.util.Key
import com.intellij.ui.dsl.builder.Panel import com.intellij.ui.dsl.builder.Panel
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.UUID import java.util.*
import java.util.function.Supplier import java.util.function.Supplier
class ZigToolchainEditor(private val sharedState: ZigProjectConfigurationProvider.IUserDataBridge): class ZigToolchainEditor(private val sharedState: ZigProjectConfigurationProvider.IUserDataBridge):
@ -60,7 +60,7 @@ class ZigToolchainEditor(private val sharedState: ZigProjectConfigurationProvide
} }
override fun attach(p: Panel): Unit = with(p) { override fun attach(panel: Panel): Unit = with(panel) {
row(ZigBrainsBundle.message( row(ZigBrainsBundle.message(
if (sharedState.getUserData(PROJECT_KEY)?.isDefault == true) if (sharedState.getUserData(PROJECT_KEY)?.isDefault == true)
"settings.toolchain.editor.toolchain-default.label" "settings.toolchain.editor.toolchain-default.label"
@ -75,7 +75,7 @@ class ZigToolchainEditor(private val sharedState: ZigProjectConfigurationProvide
views.addAll(createZigToolchainExtensionPanels(sharedState, PanelState.ProjectEditor)) views.addAll(createZigToolchainExtensionPanels(sharedState, PanelState.ProjectEditor))
myViews = views myViews = views
} }
views.forEach { it.attach(p) } views.forEach { it.attach(panel) }
} }
override fun onSelection(uuid: UUID?) { override fun onSelection(uuid: UUID?) {
@ -89,6 +89,8 @@ class ZigToolchainEditor(private val sharedState: ZigProjectConfigurationProvide
} }
override fun isModified(context: Project): Boolean { override fun isModified(context: Project): Boolean {
if (isEmpty)
return false
val uuid = selectedUUID val uuid = selectedUUID
if (ZigToolchainService.getInstance(context).toolchainUUID != selectedUUID) { if (ZigToolchainService.getInstance(context).toolchainUUID != selectedUUID) {
return true return true

View file

@ -26,11 +26,7 @@ import com.falsepattern.zigbrains.Icons
import com.falsepattern.zigbrains.ZigBrainsBundle import com.falsepattern.zigbrains.ZigBrainsBundle
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
import com.falsepattern.zigbrains.project.toolchain.base.render import com.falsepattern.zigbrains.project.toolchain.base.render
import com.falsepattern.zigbrains.shared.ui.ListElem import com.falsepattern.zigbrains.shared.ui.*
import com.falsepattern.zigbrains.shared.ui.ZBCellRenderer
import com.falsepattern.zigbrains.shared.ui.ZBComboBox
import com.falsepattern.zigbrains.shared.ui.ZBContext
import com.falsepattern.zigbrains.shared.ui.ZBModel
import com.intellij.icons.AllIcons import com.intellij.icons.AllIcons
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.ui.SimpleTextAttributes import com.intellij.ui.SimpleTextAttributes

View file

@ -27,7 +27,6 @@ import com.intellij.openapi.options.Configurable
import com.intellij.openapi.util.Disposer import com.intellij.openapi.util.Disposer
import com.intellij.ui.dsl.builder.Panel import com.intellij.ui.dsl.builder.Panel
import com.intellij.ui.dsl.builder.panel import com.intellij.ui.dsl.builder.panel
import java.util.ArrayList
import javax.swing.JComponent import javax.swing.JComponent
interface SubConfigurable<T>: Disposable { interface SubConfigurable<T>: Disposable {

View file

@ -22,7 +22,7 @@
package com.falsepattern.zigbrains.shared package com.falsepattern.zigbrains.shared
import java.util.UUID import java.util.*
fun String.asUUID(): UUID? = UUID.fromString(this) fun String.asUUID(): UUID? = UUID.fromString(this)
fun UUID.asString(): String = toString() fun UUID.asString(): String = toString()

View file

@ -26,8 +26,7 @@ import com.intellij.openapi.components.SerializablePersistentStateComponent
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.lang.ref.WeakReference import java.lang.ref.WeakReference
import java.util.UUID import java.util.*
import kotlin.collections.any
typealias UUIDStorage<T> = Map<String, T> typealias UUIDStorage<T> = Map<String, T>

View file

@ -130,13 +130,14 @@ fun createCommandLineSafe(
} }
@Throws(ExecutionException::class) @Throws(ExecutionException::class)
suspend fun GeneralCommandLine.startIPCAwareProcess(project: Project?, emulateTerminal: Boolean = false): ZigProcessHandler { suspend fun GeneralCommandLine.startIPCAwareProcess(project: Project?, emulateTerminal: Boolean = false): ZigProcessHandler.IPCAware {
val original = this.commandLineString
val ipc = if (project != null && !emulateTerminal) IPCUtil.wrapWithIPC(this) else null val ipc = if (project != null && !emulateTerminal) IPCUtil.wrapWithIPC(this) else null
val cli = ipc?.cli ?: this val cli = ipc?.cli ?: this
if (emulateTerminal && OS.CURRENT != OS.Windows && !cli.environment.contains("TERM")) { if (emulateTerminal && OS.CURRENT != OS.Windows && !cli.environment.contains("TERM")) {
cli.withEnvironment("TERM", "xterm-256color") cli.withEnvironment("TERM", "xterm-256color")
} }
val handler = ZigProcessHandler(cli) val handler = ZigProcessHandler.IPCAware(original, cli)
ProcessTerminatedListener.attach(handler) ProcessTerminatedListener.attach(handler)
if (ipc != null) { if (ipc != null) {

View file

@ -45,7 +45,7 @@ import com.intellij.ui.dsl.builder.panel
import com.intellij.util.concurrency.annotations.RequiresEdt import com.intellij.util.concurrency.annotations.RequiresEdt
import java.awt.Component import java.awt.Component
import java.nio.file.Path import java.nio.file.Path
import java.util.Vector import java.util.*
import javax.swing.DefaultComboBoxModel import javax.swing.DefaultComboBoxModel
import javax.swing.JList import javax.swing.JList
import javax.swing.event.DocumentEvent import javax.swing.event.DocumentEvent
@ -76,10 +76,10 @@ abstract class Downloader<T, V: VersionInfo>(val component: Component) {
protected abstract val windowTitle: String protected abstract val windowTitle: String
protected abstract val versionInfoFetchTitle: @NlsContexts.ProgressTitle String protected abstract val versionInfoFetchTitle: @NlsContexts.ProgressTitle String
protected abstract val suggestedPath: Path?
protected abstract fun downloadProgressTitle(version: V): @NlsContexts.ProgressTitle String protected abstract fun downloadProgressTitle(version: V): @NlsContexts.ProgressTitle String
protected abstract fun localSelector(): LocalSelector<T> protected abstract fun localSelector(): LocalSelector<T>
protected abstract suspend fun downloadVersionList(): List<V> protected abstract suspend fun downloadVersionList(): List<V>
protected abstract fun getSuggestedPath(): Path?
@RequiresEdt @RequiresEdt
private fun selectVersion(info: List<V>, selector: LocalSelector<T>): Pair<Path, V>? { private fun selectVersion(info: List<V>, selector: LocalSelector<T>): Pair<Path, V>? {
@ -131,7 +131,7 @@ abstract class Downloader<T, V: VersionInfo>(val component: Component) {
}) })
var archiveSizeCell: Cell<*>? = null var archiveSizeCell: Cell<*>? = null
fun detect(item: V) { fun detect(item: V) {
outputPath.text = getSuggestedPath()?.resolve(item.version.rawVersion)?.pathString ?: "" outputPath.text = suggestedPath?.resolve(item.version.rawVersion)?.pathString ?: ""
val size = item.dist.size val size = item.dist.size
val sizeMb = size / (1024f * 1024f) val sizeMb = size / (1024f * 1024f)
archiveSizeCell?.comment?.text = ZigBrainsBundle.message("settings.shared.downloader.archive-size.text", "%.2fMB".format(sizeMb)) archiveSizeCell?.comment?.text = ZigBrainsBundle.message("settings.shared.downloader.archive-size.text", "%.2fMB".format(sizeMb))

View file

@ -41,11 +41,13 @@ import com.intellij.ui.components.textFieldWithBrowseButton
import com.intellij.ui.dsl.builder.AlignX import com.intellij.ui.dsl.builder.AlignX
import com.intellij.ui.dsl.builder.panel import com.intellij.ui.dsl.builder.panel
import com.intellij.util.concurrency.annotations.RequiresEdt import com.intellij.util.concurrency.annotations.RequiresEdt
import com.intellij.util.system.OS
import java.awt.Component import java.awt.Component
import java.nio.file.Path import java.nio.file.Path
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
import javax.swing.Icon import javax.swing.Icon
import javax.swing.event.DocumentEvent import javax.swing.event.DocumentEvent
import kotlin.io.path.isDirectory
import kotlin.io.path.pathString import kotlin.io.path.pathString
abstract class LocalSelector<T>(val component: Component) { abstract class LocalSelector<T>(val component: Component) {
@ -136,3 +138,15 @@ abstract class LocalSelector<T>(val component: Component) {
val errorText: String, val errorText: String,
) )
} }
val homePath: Path? by lazy {
System.getProperty("user.home")?.toNioPathOrNull()?.takeIf { it.isDirectory() }
}
val xdgDataHome: Path? by lazy {
when(OS.CURRENT) {
OS.macOS -> homePath?.resolve("Library")
OS.Windows -> System.getenv("LOCALAPPDATA")?.toNioPathOrNull()
else -> System.getenv("XDG_DATA_HOME")?.toNioPathOrNull() ?: homePath?.resolve(Path.of(".local", "share"))
}?.takeIf { it.isDirectory() }
}

View file

@ -23,7 +23,6 @@
package com.falsepattern.zigbrains.shared.downloader package com.falsepattern.zigbrains.shared.downloader
import com.falsepattern.zigbrains.ZigBrainsBundle import com.falsepattern.zigbrains.ZigBrainsBundle
import com.falsepattern.zigbrains.project.toolchain.downloader.ZigVersionInfo
import com.falsepattern.zigbrains.shared.Unarchiver import com.falsepattern.zigbrains.shared.Unarchiver
import com.falsepattern.zigbrains.shared.downloader.VersionInfo.Tarball import com.falsepattern.zigbrains.shared.downloader.VersionInfo.Tarball
import com.intellij.openapi.application.PathManager import com.intellij.openapi.application.PathManager

View file

@ -24,8 +24,11 @@ package com.falsepattern.zigbrains.shared.ui
import com.falsepattern.zigbrains.shared.UUIDMapSerializable import com.falsepattern.zigbrains.shared.UUIDMapSerializable
import com.intellij.openapi.ui.NamedConfigurable import com.intellij.openapi.ui.NamedConfigurable
import com.intellij.ui.components.JBScrollPane
import java.awt.Component import java.awt.Component
import java.util.UUID import java.awt.Dimension
import java.util.*
import javax.swing.JComponent
interface UUIDComboBoxDriver<T> { interface UUIDComboBoxDriver<T> {
val theMap: UUIDMapSerializable.Converting<T, *, *> val theMap: UUIDMapSerializable.Converting<T, *, *>
@ -34,4 +37,15 @@ interface UUIDComboBoxDriver<T> {
fun createComboBox(model: ZBModel<T>): ZBComboBox<T> fun createComboBox(model: ZBModel<T>): ZBComboBox<T>
suspend fun resolvePseudo(context: Component, elem: ListElem.Pseudo<T>): UUID? suspend fun resolvePseudo(context: Component, elem: ListElem.Pseudo<T>): UUID?
fun createNamedConfigurable(uuid: UUID, elem: T): NamedConfigurable<UUID> fun createNamedConfigurable(uuid: UUID, elem: T): NamedConfigurable<UUID>
companion object {
fun wrapModal(component: JComponent, modal: Boolean): JComponent {
if (modal) {
component.preferredSize = Dimension(640, 480)
return component
} else {
return JBScrollPane(component)
}
}
}
} }

View file

@ -39,7 +39,7 @@ import com.intellij.util.IconUtil
import com.intellij.util.asSafely import com.intellij.util.asSafely
import com.intellij.util.concurrency.annotations.RequiresEdt import com.intellij.util.concurrency.annotations.RequiresEdt
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.util.UUID import java.util.*
import javax.swing.JComponent import javax.swing.JComponent
import javax.swing.tree.DefaultTreeModel import javax.swing.tree.DefaultTreeModel

View file

@ -28,12 +28,10 @@ import com.falsepattern.zigbrains.shared.StorageChangeListener
import com.falsepattern.zigbrains.shared.coroutine.asContextElement import com.falsepattern.zigbrains.shared.coroutine.asContextElement
import com.falsepattern.zigbrains.shared.coroutine.launchWithEDT import com.falsepattern.zigbrains.shared.coroutine.launchWithEDT
import com.falsepattern.zigbrains.shared.coroutine.withEDTContext import com.falsepattern.zigbrains.shared.coroutine.withEDTContext
import com.falsepattern.zigbrains.shared.ui.ListElem
import com.falsepattern.zigbrains.shared.zigCoroutineScope import com.falsepattern.zigbrains.shared.zigCoroutineScope
import com.intellij.openapi.Disposable import com.intellij.openapi.Disposable
import com.intellij.openapi.application.EDT import com.intellij.openapi.application.EDT
import com.intellij.openapi.application.ModalityState import com.intellij.openapi.application.ModalityState
import com.intellij.openapi.application.runInEdt
import com.intellij.openapi.observable.util.whenListChanged import com.intellij.openapi.observable.util.whenListChanged
import com.intellij.openapi.options.ShowSettingsUtil import com.intellij.openapi.options.ShowSettingsUtil
import com.intellij.openapi.ui.DialogWrapper import com.intellij.openapi.ui.DialogWrapper
@ -41,12 +39,11 @@ import com.intellij.ui.dsl.builder.AlignX
import com.intellij.ui.dsl.builder.Row import com.intellij.ui.dsl.builder.Row
import com.intellij.util.concurrency.annotations.RequiresEdt import com.intellij.util.concurrency.annotations.RequiresEdt
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Runnable
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.awt.event.ItemEvent import java.awt.event.ItemEvent
import java.util.UUID import java.util.*
import javax.swing.JButton import javax.swing.JButton
abstract class UUIDMapSelector<T>(val driver: UUIDComboBoxDriver<T>): Disposable { abstract class UUIDMapSelector<T>(val driver: UUIDComboBoxDriver<T>): Disposable {
@ -82,6 +79,8 @@ abstract class UUIDMapSelector<T>(val driver: UUIDComboBoxDriver<T>): Disposable
} }
} }
protected val isEmpty: Boolean get() = model.isEmpty
protected open fun onSelection(uuid: UUID?) {} protected open fun onSelection(uuid: UUID?) {}
private fun refreshButtonState(item: ListElem<*>) { private fun refreshButtonState(item: ListElem<*>) {
@ -162,7 +161,7 @@ abstract class UUIDMapSelector<T>(val driver: UUIDComboBoxDriver<T>): Disposable
protected fun attachComboBoxRow(row: Row): Unit = with(row) { protected fun attachComboBoxRow(row: Row): Unit = with(row) {
cell(comboBox).resizableColumn().align(AlignX.FILL) cell(comboBox).resizableColumn().align(AlignX.FILL)
button(ZigBrainsBundle.message("settings.toolchain.editor.toolchain.edit-button.name")) { e -> button(ZigBrainsBundle.message("settings.toolchain.editor.toolchain.edit-button.name")) {
zigCoroutineScope.launchWithEDT(comboBox.asContextElement()) { zigCoroutineScope.launchWithEDT(comboBox.asContextElement()) {
var selectedUUID = comboBox.selectedUUID ?: return@launchWithEDT var selectedUUID = comboBox.selectedUUID ?: return@launchWithEDT
val elem = driver.theMap[selectedUUID] ?: return@launchWithEDT val elem = driver.theMap[selectedUUID] ?: return@launchWithEDT

View file

@ -24,7 +24,7 @@ package com.falsepattern.zigbrains.shared.ui
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map
import java.util.UUID import java.util.*
sealed interface ListElemIn<T> sealed interface ListElemIn<T>

View file

@ -31,12 +31,7 @@ import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.ComboBox import com.intellij.openapi.ui.ComboBox
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil import com.intellij.openapi.util.text.StringUtil
import com.intellij.ui.CellRendererPanel import com.intellij.ui.*
import com.intellij.ui.CollectionComboBoxModel
import com.intellij.ui.ColoredListCellRenderer
import com.intellij.ui.GroupHeaderSeparator
import com.intellij.ui.SimpleColoredComponent
import com.intellij.ui.SimpleTextAttributes
import com.intellij.ui.components.panels.OpaquePanel import com.intellij.ui.components.panels.OpaquePanel
import com.intellij.ui.popup.list.ComboBoxPopup import com.intellij.ui.popup.list.ComboBoxPopup
import com.intellij.util.concurrency.annotations.RequiresEdt import com.intellij.util.concurrency.annotations.RequiresEdt
@ -47,13 +42,11 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.awt.BorderLayout import java.awt.BorderLayout
import java.awt.Component import java.awt.Component
import java.util.IdentityHashMap import java.util.*
import java.util.UUID
import java.util.function.Consumer import java.util.function.Consumer
import javax.accessibility.AccessibleContext import javax.accessibility.AccessibleContext
import javax.swing.JList import javax.swing.JList
import javax.swing.border.Border import javax.swing.border.Border
import kotlin.io.path.pathString
class ZBComboBoxPopup<T>( class ZBComboBoxPopup<T>(
context: ZBContext<T>, context: ZBContext<T>,
@ -257,16 +250,16 @@ abstract class ZBCellRenderer<T>(val getModel: () -> ZBModel<T>) : ColoredListCe
} }
fun renderPathNameComponent(path: String, name: String?, nameFallback: String, component: SimpleColoredComponent, isSuggestion: Boolean, isSelected: Boolean) { fun renderPathNameComponent(path: String, name: String?, nameFallback: String, component: SimpleColoredComponent, isSuggestion: Boolean, isSelected: Boolean) {
val path = presentDetectedPath(path) val thePath = presentDetectedPath(path)
val primary: String val primary: String
var secondary: String? var secondary: String?
val tooltip: String? val tooltip: String?
if (isSuggestion) { if (isSuggestion) {
primary = path primary = thePath
secondary = name secondary = name
} else { } else {
primary = name ?: nameFallback primary = name ?: nameFallback
secondary = path secondary = thePath
} }
if (isSelected) { if (isSelected) {
tooltip = secondary tooltip = secondary
@ -284,12 +277,12 @@ fun renderPathNameComponent(path: String, name: String?, nameFallback: String, c
fun presentDetectedPath(home: String, maxLength: Int = 50, suffixLength: Int = 30): String { fun presentDetectedPath(home: String, maxLength: Int = 50, suffixLength: Int = 30): String {
//for macOS, let's try removing Bundle internals //for macOS, let's try removing Bundle internals
var home = home var theHome = home
home = StringUtil.trimEnd(home, "/Contents/Home") //NON-NLS theHome = StringUtil.trimEnd(theHome, "/Contents/Home") //NON-NLS
home = StringUtil.trimEnd(home, "/Contents/MacOS") //NON-NLS theHome = StringUtil.trimEnd(theHome, "/Contents/MacOS") //NON-NLS
home = FileUtil.getLocationRelativeToUserHome(home, false) theHome = FileUtil.getLocationRelativeToUserHome(theHome, false)
home = StringUtil.shortenTextWithEllipsis(home, maxLength, suffixLength) theHome = StringUtil.shortenTextWithEllipsis(theHome, maxLength, suffixLength)
return home return theHome
} }
private val EMPTY_ICON = EmptyIcon.create(1, 16) private val EMPTY_ICON = EmptyIcon.create(1, 16)

View file

@ -91,7 +91,8 @@ configuration.test.marker-name=all tests in {0}
configuration.build.name=Zig build configuration.build.name=Zig build
configuration.build.suggested-name=Build configuration.build.suggested-name=Build
configuration.build.description=Execute "zig build" with custom steps configuration.build.description=Execute "zig build" with custom steps
configuration.build.marker-name=Build and Run configuration.build.marker-run=Build and Run
configuration.build.marker-test=Build and Test
settings.project.group.title=Zig Settings settings.project.group.title=Zig Settings
settings.project.label.direnv=Use direnv settings.project.label.direnv=Use direnv
settings.project.label.toolchain=Toolchain location settings.project.label.toolchain=Toolchain location

View file

@ -1,13 +1,13 @@
pluginName=ZigBrains pluginName=ZigBrains
pluginRepositoryUrl=https://github.com/FalsePattern/ZigBrains pluginRepositoryUrl=https://github.com/FalsePattern/ZigBrains
pluginVersion=24.0.1 pluginVersion=25.2.0
pluginSinceBuild=243 pluginSinceBuild=251
pluginUntilBuild= pluginUntilBuild=
ideaCommunityVersion=2024.3 ideaCommunityVersion=2025.1
clionVersion=2024.3 clionVersion=2025.1
useInstaller=true useInstaller=true
javaVersion=21 javaVersion=21
# ideaCommunity / clion # ideaCommunity / clion
@ -17,6 +17,8 @@ lsp4jVersion=0.21.1
lsp4ijVersion=0.12.0 lsp4ijVersion=0.12.0
lsp4ijNightly=false lsp4ijNightly=false
serializationVersion=1.7.3
kotlin.stdlib.default.dependency=false kotlin.stdlib.default.dependency=false
kotlin.code.style=official kotlin.code.style=official
org.gradle.configuration-cache=true org.gradle.configuration-cache=true

View file

@ -8,12 +8,15 @@ val lsp4ijVersion: String by project
val lsp4jVersion: String by project val lsp4jVersion: String by project
val ideaCommunityVersion: String by project val ideaCommunityVersion: String by project
val useInstaller = property("useInstaller").toString().toBoolean() val useInstaller = property("useInstaller").toString().toBoolean()
val serializationVersion: String by project
dependencies { dependencies {
intellijPlatform { intellijPlatform {
create(IntelliJPlatformType.IntellijIdeaCommunity, ideaCommunityVersion, useInstaller = useInstaller) create(IntelliJPlatformType.IntellijIdeaCommunity, ideaCommunityVersion, useInstaller = useInstaller)
} }
compileOnly("org.jetbrains.kotlinx:kotlinx-serialization-core:1.7.3") compileOnly("org.jetbrains.kotlinx:kotlinx-serialization-core-jvm:$serializationVersion") {
isTransitive = false
}
compileOnly("com.redhat.devtools.intellij:lsp4ij:$lsp4ijVersion") compileOnly("com.redhat.devtools.intellij:lsp4ij:$lsp4ijVersion")
compileOnly("org.eclipse.lsp4j:org.eclipse.lsp4j:$lsp4jVersion") compileOnly("org.eclipse.lsp4j:org.eclipse.lsp4j:$lsp4jVersion")
implementation(project(":core")) { implementation(project(":core")) {

View file

@ -24,7 +24,6 @@ package com.falsepattern.zigbrains.lsp
import com.falsepattern.zigbrains.lsp.config.ZLSConfigProviderBase import com.falsepattern.zigbrains.lsp.config.ZLSConfigProviderBase
import com.falsepattern.zigbrains.lsp.zls.zls import com.falsepattern.zigbrains.lsp.zls.zls
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainService
import com.intellij.execution.configurations.GeneralCommandLine import com.intellij.execution.configurations.GeneralCommandLine
import com.intellij.notification.Notification import com.intellij.notification.Notification
import com.intellij.notification.NotificationType import com.intellij.notification.NotificationType

View file

@ -68,7 +68,14 @@ class ZigLanguageServerFactory: LanguageServerFactory, LanguageServerEnablementS
} }
features.inlayHintFeature = object: LSPInlayHintFeature() { features.inlayHintFeature = object: LSPInlayHintFeature() {
override fun isEnabled(file: PsiFile): Boolean { override fun isEnabled(file: PsiFile): Boolean {
return project.zls?.settings?.inlayHints == true val settings = project.zls?.settings ?: return false
if (!settings.inlayHints)
return false
val maxFileSizeKb = settings.inlayHintsMaxFileSizeKb
if (maxFileSizeKb == 0)
return true
val fileSizeKb = file.fileDocument.textLength / 1024
return fileSizeKb <= maxFileSizeKb
} }
} }
return features return features

View file

@ -23,8 +23,6 @@
package com.falsepattern.zigbrains.lsp.settings package com.falsepattern.zigbrains.lsp.settings
import com.falsepattern.zigbrains.lsp.config.SemanticTokens import com.falsepattern.zigbrains.lsp.config.SemanticTokens
import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider
import com.intellij.openapi.project.Project
import com.intellij.util.xmlb.annotations.Attribute import com.intellij.util.xmlb.annotations.Attribute
import org.jetbrains.annotations.NonNls import org.jetbrains.annotations.NonNls
@ -32,6 +30,7 @@ import org.jetbrains.annotations.NonNls
data class ZLSSettings( data class ZLSSettings(
@JvmField @Attribute val zlsConfigPath: @NonNls String = "", @JvmField @Attribute val zlsConfigPath: @NonNls String = "",
@JvmField @Attribute val inlayHints: Boolean = true, @JvmField @Attribute val inlayHints: Boolean = true,
@JvmField @Attribute val inlayHintsMaxFileSizeKb: Int = 128,
@JvmField @Attribute val enable_snippets: Boolean = true, @JvmField @Attribute val enable_snippets: Boolean = true,
@JvmField @Attribute val enable_argument_placeholders: Boolean = true, @JvmField @Attribute val enable_argument_placeholders: Boolean = true,
@JvmField @Attribute val completion_label_details: Boolean = true, @JvmField @Attribute val completion_label_details: Boolean = true,

View file

@ -35,6 +35,9 @@ import com.intellij.ui.dsl.builder.AlignX
import com.intellij.ui.dsl.builder.Panel import com.intellij.ui.dsl.builder.Panel
import com.intellij.ui.dsl.builder.Row import com.intellij.ui.dsl.builder.Row
import org.jetbrains.annotations.PropertyKey import org.jetbrains.annotations.PropertyKey
import javax.swing.text.AttributeSet
import javax.swing.text.DocumentFilter
import javax.swing.text.PlainDocument
@Suppress("PrivatePropertyName") @Suppress("PrivatePropertyName")
class ZLSSettingsPanel() : ImmutableElementPanel<ZLSSettings> { class ZLSSettingsPanel() : ImmutableElementPanel<ZLSSettings> {
@ -44,6 +47,27 @@ class ZLSSettingsPanel() : ImmutableElementPanel<ZLSSettings> {
.withTitle(ZLSBundle.message("settings.zls-config-path.browse.title")) .withTitle(ZLSBundle.message("settings.zls-config-path.browse.title"))
).also { Disposer.register(this, it) } ).also { Disposer.register(this, it) }
private val inlayHints = JBCheckBox() private val inlayHints = JBCheckBox()
private val inlayHintsMaxFileSize = ExtendableTextField(5).also { (it.document as PlainDocument).documentFilter = object: DocumentFilter() {
override fun insertString(fb: FilterBypass?, offset: Int, string: String?, attr: AttributeSet?) {
if (string != null && !string.isEmpty() && string.toIntOrNull() == null) {
return
}
super.insertString(fb, offset, string, attr)
}
override fun replace(
fb: FilterBypass?,
offset: Int,
length: Int,
text: String?,
attrs: AttributeSet?
) {
if (text != null && !text.isEmpty() && text.toIntOrNull() == null) {
return
}
super.replace(fb, offset, length, text, attrs)
}
} }
private val enable_snippets = JBCheckBox() private val enable_snippets = JBCheckBox()
private val enable_argument_placeholders = JBCheckBox() private val enable_argument_placeholders = JBCheckBox()
private val completion_label_details = JBCheckBox() private val completion_label_details = JBCheckBox()
@ -65,7 +89,7 @@ class ZLSSettingsPanel() : ImmutableElementPanel<ZLSSettings> {
private val build_runner_path = ExtendableTextField() private val build_runner_path = ExtendableTextField()
private val global_cache_path = ExtendableTextField() private val global_cache_path = ExtendableTextField()
override fun attach(p: Panel): Unit = with(p) { override fun attach(panel: Panel): Unit = with(panel) {
fancyRow( fancyRow(
"settings.zls-config-path.label", "settings.zls-config-path.label",
"settings.zls-config-path.tooltip" "settings.zls-config-path.tooltip"
@ -99,6 +123,13 @@ class ZLSSettingsPanel() : ImmutableElementPanel<ZLSSettings> {
"settings.inlay-hints-enable.label", "settings.inlay-hints-enable.label",
"settings.inlay-hints-enable.tooltip" "settings.inlay-hints-enable.tooltip"
) { cell(inlayHints) } ) { cell(inlayHints) }
fancyRow(
"settings.inlay-hints-max-size.label",
"settings.inlay-hints-max-size.tooltip",
) {
cell(inlayHintsMaxFileSize)
text(ZLSBundle.message("settings.inlay-hints-max-size.unit"))
}
fancyRow( fancyRow(
"settings.inlay_hints_show_variable_type_hints.label", "settings.inlay_hints_show_variable_type_hints.label",
"settings.inlay_hints_show_variable_type_hints.tooltip" "settings.inlay_hints_show_variable_type_hints.tooltip"
@ -174,6 +205,7 @@ class ZLSSettingsPanel() : ImmutableElementPanel<ZLSSettings> {
get() = ZLSSettings( get() = ZLSSettings(
zlsConfigPath.text, zlsConfigPath.text,
inlayHints.isSelected, inlayHints.isSelected,
inlayHintsMaxFileSize.text.toIntOrNull() ?: 128,
enable_snippets.isSelected, enable_snippets.isSelected,
enable_argument_placeholders.isSelected, enable_argument_placeholders.isSelected,
completion_label_details.isSelected, completion_label_details.isSelected,
@ -198,6 +230,7 @@ class ZLSSettingsPanel() : ImmutableElementPanel<ZLSSettings> {
set(value) { set(value) {
zlsConfigPath.text = value.zlsConfigPath zlsConfigPath.text = value.zlsConfigPath
inlayHints.isSelected = value.inlayHints inlayHints.isSelected = value.inlayHints
inlayHintsMaxFileSize.text = value.inlayHintsMaxFileSizeKb.toString()
enable_snippets.isSelected = value.enable_snippets enable_snippets.isSelected = value.enable_snippets
enable_argument_placeholders.isSelected = value.enable_argument_placeholders enable_argument_placeholders.isSelected = value.enable_argument_placeholders
completion_label_details.isSelected = value.completion_label_details completion_label_details.isSelected = value.completion_label_details

View file

@ -22,15 +22,14 @@
package com.falsepattern.zigbrains.lsp.zls package com.falsepattern.zigbrains.lsp.zls
import com.falsepattern.zigbrains.shared.ui.UUIDComboBoxDriver.Companion.wrapModal
import com.intellij.openapi.ui.NamedConfigurable import com.intellij.openapi.ui.NamedConfigurable
import com.intellij.openapi.util.NlsContexts import com.intellij.openapi.util.NlsContexts
import com.intellij.openapi.util.NlsSafe
import com.intellij.ui.dsl.builder.panel import com.intellij.ui.dsl.builder.panel
import java.awt.Dimension import java.util.*
import java.util.UUID
import javax.swing.JComponent import javax.swing.JComponent
class ZLSConfigurable(val uuid: UUID, zls: ZLSVersion): NamedConfigurable<UUID>() { class ZLSConfigurable(val uuid: UUID, zls: ZLSVersion, private val modal: Boolean): NamedConfigurable<UUID>() {
var zls: ZLSVersion = zls var zls: ZLSVersion = zls
set(value) { set(value) {
zlsInstallations[uuid] = value zlsInstallations[uuid] = value
@ -60,8 +59,7 @@ class ZLSConfigurable(val uuid: UUID, zls: ZLSVersion): NamedConfigurable<UUID>(
val p = panel { val p = panel {
view.attach(this@panel) view.attach(this@panel)
} }
p.preferredSize = Dimension(640, 480) return wrapModal(p, modal)
return p
} }
override fun getDisplayName(): @NlsContexts.ConfigurableName String? { override fun getDisplayName(): @NlsContexts.ConfigurableName String? {

View file

@ -25,7 +25,10 @@ package com.falsepattern.zigbrains.lsp.zls
import com.falsepattern.zigbrains.lsp.zls.ZLSInstallationsService.MyState import com.falsepattern.zigbrains.lsp.zls.ZLSInstallationsService.MyState
import com.falsepattern.zigbrains.shared.UUIDMapSerializable import com.falsepattern.zigbrains.shared.UUIDMapSerializable
import com.falsepattern.zigbrains.shared.UUIDStorage import com.falsepattern.zigbrains.shared.UUIDStorage
import com.intellij.openapi.components.* import com.intellij.openapi.components.Service
import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage
import com.intellij.openapi.components.service
@Service(Service.Level.APP) @Service(Service.Level.APP)
@State( @State(

View file

@ -22,8 +22,8 @@
package com.falsepattern.zigbrains.lsp.zls package com.falsepattern.zigbrains.lsp.zls
import com.falsepattern.zigbrains.lsp.ZLSBundle
import com.falsepattern.zigbrains.lsp.settings.ZLSSettingsPanel import com.falsepattern.zigbrains.lsp.settings.ZLSSettingsPanel
import com.falsepattern.zigbrains.project.toolchain.local.LocalZigToolchain
import com.falsepattern.zigbrains.project.toolchain.ui.ImmutableNamedElementPanelBase import com.falsepattern.zigbrains.project.toolchain.ui.ImmutableNamedElementPanelBase
import com.falsepattern.zigbrains.shared.cli.call import com.falsepattern.zigbrains.shared.cli.call
import com.falsepattern.zigbrains.shared.cli.createCommandLineSafe import com.falsepattern.zigbrains.shared.cli.createCommandLineSafe
@ -49,7 +49,7 @@ import kotlin.io.path.pathString
class ZLSPanel() : ImmutableNamedElementPanelBase<ZLSVersion>() { class ZLSPanel() : ImmutableNamedElementPanelBase<ZLSVersion>() {
private val pathToZLS = textFieldWithBrowseButton( private val pathToZLS = textFieldWithBrowseButton(
null, null,
FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor().withTitle("Path to the zls executable") FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor().withTitle(ZLSBundle.message("dialog.title.zls"))
).also { ).also {
it.textField.document.addDocumentListener(object : DocumentAdapter() { it.textField.document.addDocumentListener(object : DocumentAdapter() {
override fun textChanged(e: DocumentEvent) { override fun textChanged(e: DocumentEvent) {
@ -62,36 +62,36 @@ class ZLSPanel() : ImmutableNamedElementPanelBase<ZLSVersion>() {
private var settingsPanel: ZLSSettingsPanel? = null private var settingsPanel: ZLSSettingsPanel? = null
private var debounce: Job? = null private var debounce: Job? = null
override fun attach(p: Panel): Unit = with(p) { override fun attach(panel: Panel): Unit = with(panel) {
super.attach(p) super.attach(panel)
row("Path:") { row(ZLSBundle.message("settings.panel.path.label")) {
cell(pathToZLS).resizableColumn().align(AlignX.FILL) cell(pathToZLS).resizableColumn().align(AlignX.FILL)
} }
row("Version:") { row(ZLSBundle.message("settings.panel.version.label")) {
cell(zlsVersion) cell(zlsVersion)
} }
val sp = ZLSSettingsPanel() val sp = ZLSSettingsPanel()
p.collapsibleGroup("Settings", indent = false) { panel.collapsibleGroup(ZLSBundle.message("settings.panel.settings.group.label"), indent = false) {
sp.attach(this@collapsibleGroup) sp.attach(this@collapsibleGroup)
} }
settingsPanel = sp settingsPanel = sp
} }
override fun isModified(version: ZLSVersion): Boolean { override fun isModified(elem: ZLSVersion): Boolean {
val name = nameFieldValue ?: return false val name = nameFieldValue ?: return false
val path = this.pathToZLS.text.ifBlank { null }?.toNioPathOrNull() ?: return false val path = this.pathToZLS.text.ifBlank { null }?.toNioPathOrNull() ?: return false
return name != version.name || version.path != path || settingsPanel?.isModified(version.settings) == true return name != elem.name || elem.path != path || settingsPanel?.isModified(elem.settings) == true
} }
override fun apply(version: ZLSVersion): ZLSVersion? { override fun apply(elem: ZLSVersion): ZLSVersion? {
val path = this.pathToZLS.text.ifBlank { null }?.toNioPathOrNull() ?: return null val path = this.pathToZLS.text.ifBlank { null }?.toNioPathOrNull() ?: return null
return version.copy(path = path, name = nameFieldValue ?: "", settings = settingsPanel?.apply(version.settings) ?: version.settings) return elem.copy(path = path, name = nameFieldValue ?: "", settings = settingsPanel?.apply(elem.settings) ?: elem.settings)
} }
override fun reset(version: ZLSVersion?) { override fun reset(elem: ZLSVersion?) {
nameFieldValue = version?.name ?: "" nameFieldValue = elem?.name ?: ""
this.pathToZLS.text = version?.path?.pathString ?: "" this.pathToZLS.text = elem?.path?.pathString ?: ""
settingsPanel?.reset(version?.settings) settingsPanel?.reset(elem?.settings)
dispatchUpdateUI() dispatchUpdateUI()
} }

View file

@ -28,7 +28,7 @@ import com.falsepattern.zigbrains.project.toolchain.base.withExtraData
import com.falsepattern.zigbrains.shared.asString import com.falsepattern.zigbrains.shared.asString
import com.falsepattern.zigbrains.shared.asUUID import com.falsepattern.zigbrains.shared.asUUID
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import java.util.UUID import java.util.*
fun <T: ZigToolchain> T.withZLS(uuid: UUID?): T { fun <T: ZigToolchain> T.withZLS(uuid: UUID?): T {
return withExtraData("zls_uuid", uuid?.asString()) return withExtraData("zls_uuid", uuid?.asString())

View file

@ -26,12 +26,11 @@ import com.falsepattern.zigbrains.lsp.settings.ZLSSettings
import com.falsepattern.zigbrains.shared.NamedObject import com.falsepattern.zigbrains.shared.NamedObject
import com.falsepattern.zigbrains.shared.cli.call import com.falsepattern.zigbrains.shared.cli.call
import com.falsepattern.zigbrains.shared.cli.createCommandLineSafe import com.falsepattern.zigbrains.shared.cli.createCommandLineSafe
import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.io.toNioPathOrNull import com.intellij.openapi.util.io.toNioPathOrNull
import com.intellij.util.text.SemVer import com.intellij.util.text.SemVer
import java.nio.file.Path
import com.intellij.util.xmlb.annotations.Attribute import com.intellij.util.xmlb.annotations.Attribute
import kotlin.io.path.isDirectory import com.intellij.util.xmlb.annotations.Tag
import java.nio.file.Path
import kotlin.io.path.isExecutable import kotlin.io.path.isExecutable
import kotlin.io.path.isRegularFile import kotlin.io.path.isRegularFile
import kotlin.io.path.pathString import kotlin.io.path.pathString
@ -82,6 +81,7 @@ data class ZLSVersion(val path: Path, override val name: String? = null, val set
@Attribute @Attribute
val name: String? = "", val name: String? = "",
@JvmField @JvmField
@Tag
val settings: ZLSSettings = ZLSSettings() val settings: ZLSSettings = ZLSSettings()
) { ) {
fun resolve(): ZLSVersion? { fun resolve(): ZLSVersion? {

View file

@ -22,27 +22,24 @@
package com.falsepattern.zigbrains.lsp.zls.downloader package com.falsepattern.zigbrains.lsp.zls.downloader
import com.falsepattern.zigbrains.lsp.ZLSBundle
import com.falsepattern.zigbrains.lsp.zls.ZLSVersion import com.falsepattern.zigbrains.lsp.zls.ZLSVersion
import com.falsepattern.zigbrains.lsp.zls.ui.getSuggestedZLSPath import com.falsepattern.zigbrains.lsp.zls.ui.suggestedZLSPath
import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider
import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider.IUserDataBridge import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider.IUserDataBridge
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchainConfigurable import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchainConfigurable
import com.falsepattern.zigbrains.shared.downloader.Downloader import com.falsepattern.zigbrains.shared.downloader.Downloader
import com.intellij.openapi.util.io.toNioPathOrNull
import com.intellij.util.system.OS
import java.awt.Component import java.awt.Component
import java.nio.file.Path
import kotlin.io.path.isDirectory
class ZLSDownloader(component: Component, private val data: IUserDataBridge?) : Downloader<ZLSVersion, ZLSVersionInfo>(component) { class ZLSDownloader(component: Component, private val data: IUserDataBridge?) : Downloader<ZLSVersion, ZLSVersionInfo>(component) {
override val windowTitle get() = "Install ZLS" override val windowTitle get() = ZLSBundle.message("settings.downloader.title")
override val versionInfoFetchTitle get() = "Fetching zls version information" override val versionInfoFetchTitle get() = ZLSBundle.message("settings.downloader.progress.fetch")
override fun downloadProgressTitle(version: ZLSVersionInfo) = "Installing ZLS ${version.version.rawVersion}" override val suggestedPath get() = suggestedZLSPath
override fun downloadProgressTitle(version: ZLSVersionInfo) = ZLSBundle.message("settings.downloader.progress.install", version.version.rawVersion)
override fun localSelector() = ZLSLocalSelector(component) override fun localSelector() = ZLSLocalSelector(component)
override suspend fun downloadVersionList(): List<ZLSVersionInfo> { override suspend fun downloadVersionList(): List<ZLSVersionInfo> {
val toolchain = data?.getUserData(ZigToolchainConfigurable.TOOLCHAIN_KEY)?.get() val toolchain = data?.getUserData(ZigToolchainConfigurable.TOOLCHAIN_KEY)?.get()
val project = data?.getUserData(ZigProjectConfigurationProvider.PROJECT_KEY) val project = data?.getUserData(ZigProjectConfigurationProvider.PROJECT_KEY)
return ZLSVersionInfo.downloadVersionInfoFor(toolchain, project) return ZLSVersionInfo.downloadVersionInfoFor(toolchain, project)
} }
override fun getSuggestedPath() = getSuggestedZLSPath()
} }

View file

@ -22,6 +22,7 @@
package com.falsepattern.zigbrains.lsp.zls.downloader package com.falsepattern.zigbrains.lsp.zls.downloader
import com.falsepattern.zigbrains.lsp.ZLSBundle
import com.falsepattern.zigbrains.lsp.zls.ZLSVersion import com.falsepattern.zigbrains.lsp.zls.ZLSVersion
import com.falsepattern.zigbrains.lsp.zls.zlsInstallations import com.falsepattern.zigbrains.lsp.zls.zlsInstallations
import com.falsepattern.zigbrains.shared.downloader.LocalSelector import com.falsepattern.zigbrains.shared.downloader.LocalSelector
@ -36,9 +37,9 @@ import kotlin.io.path.isDirectory
class ZLSLocalSelector(component: Component) : LocalSelector<ZLSVersion>(component) { class ZLSLocalSelector(component: Component) : LocalSelector<ZLSVersion>(component) {
override val windowTitle: String override val windowTitle: String
get() = "Select ZLS from disk" get() = ZLSBundle.message("settings.local-selector.title")
override val descriptor: FileChooserDescriptor override val descriptor: FileChooserDescriptor
get() = FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor().withTitle("ZLS binary") get() = FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor().withTitle(ZLSBundle.message("settings.local-selector.chooser.title"))
override suspend fun browse(preSelected: Path?): ZLSVersion? { override suspend fun browse(preSelected: Path?): ZLSVersion? {
if (preSelected?.isDirectory() == true) { if (preSelected?.isDirectory() == true) {
@ -54,12 +55,12 @@ class ZLSLocalSelector(component: Component) : LocalSelector<ZLSVersion>(compone
null, null,
false, false,
AllIcons.General.Error, AllIcons.General.Error,
"Invalid ZLS path", ZLSBundle.message("settings.local-selector.state.invalid"),
) else VerifyResult( ) else VerifyResult(
null, null,
true, true,
AllIcons.General.Information, AllIcons.General.Information,
"ZLS path OK" ZLSBundle.message("settings.local-selector.state.ok")
) )
if (zls != null) { if (zls != null) {
zls = zlsInstallations.withUniqueName(zls) zls = zlsInstallations.withUniqueName(zls)

View file

@ -22,8 +22,8 @@
package com.falsepattern.zigbrains.lsp.zls.downloader package com.falsepattern.zigbrains.lsp.zls.downloader
import com.falsepattern.zigbrains.lsp.ZLSBundle
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchain
import com.falsepattern.zigbrains.project.toolchain.downloader.ZigVersionInfo
import com.falsepattern.zigbrains.shared.downloader.VersionInfo import com.falsepattern.zigbrains.shared.downloader.VersionInfo
import com.falsepattern.zigbrains.shared.downloader.VersionInfo.Tarball import com.falsepattern.zigbrains.shared.downloader.VersionInfo.Tarball
import com.falsepattern.zigbrains.shared.downloader.getTarballIfCompatible import com.falsepattern.zigbrains.shared.downloader.getTarballIfCompatible
@ -37,12 +37,7 @@ import com.intellij.util.text.SemVer
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json import kotlinx.serialization.json.*
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.decodeFromJsonElement
import kotlinx.serialization.json.decodeFromStream
import java.net.URLEncoder import java.net.URLEncoder
@JvmRecord @JvmRecord
@ -64,7 +59,7 @@ data class ZLSVersionInfo(
val service = DownloadableFileService.getInstance() val service = DownloadableFileService.getInstance()
val tempFile = FileUtil.createTempFile(tempPluginDir, "zls_version_info", ".json", false, false) val tempFile = FileUtil.createTempFile(tempPluginDir, "zls_version_info", ".json", false, false)
val desc = service.createFileDescription(url, tempFile.name) val desc = service.createFileDescription(url, tempFile.name)
val downloader = service.createDownloader(listOf(desc), "ZLS version information") val downloader = service.createDownloader(listOf(desc), ZLSBundle.message("settings.downloader.service.index"))
val downloadResults = coroutineToIndicator { val downloadResults = coroutineToIndicator {
downloader.download(tempPluginDir) downloader.download(tempPluginDir)
} }

View file

@ -33,21 +33,14 @@ import com.falsepattern.zigbrains.lsp.zls.zlsInstallations
import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider import com.falsepattern.zigbrains.project.settings.ZigProjectConfigurationProvider
import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchainConfigurable.Companion.TOOLCHAIN_KEY import com.falsepattern.zigbrains.project.toolchain.base.ZigToolchainConfigurable.Companion.TOOLCHAIN_KEY
import com.falsepattern.zigbrains.shared.UUIDMapSerializable import com.falsepattern.zigbrains.shared.UUIDMapSerializable
import com.falsepattern.zigbrains.shared.ui.ListElem import com.falsepattern.zigbrains.shared.downloader.homePath
import com.falsepattern.zigbrains.shared.downloader.xdgDataHome
import com.falsepattern.zigbrains.shared.ui.*
import com.falsepattern.zigbrains.shared.ui.ListElem.One.Actual import com.falsepattern.zigbrains.shared.ui.ListElem.One.Actual
import com.falsepattern.zigbrains.shared.ui.ListElemIn
import com.falsepattern.zigbrains.shared.ui.Separator
import com.falsepattern.zigbrains.shared.ui.UUIDComboBoxDriver
import com.falsepattern.zigbrains.shared.ui.ZBComboBox
import com.falsepattern.zigbrains.shared.ui.ZBContext
import com.falsepattern.zigbrains.shared.ui.ZBModel
import com.falsepattern.zigbrains.shared.ui.asPending
import com.falsepattern.zigbrains.shared.withUniqueName import com.falsepattern.zigbrains.shared.withUniqueName
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.NamedConfigurable import com.intellij.openapi.ui.NamedConfigurable
import com.intellij.openapi.util.SystemInfo import com.intellij.openapi.util.SystemInfo
import com.intellij.openapi.util.io.toNioPathOrNull
import com.intellij.util.system.OS
import com.intellij.util.text.SemVer import com.intellij.util.text.SemVer
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@ -57,7 +50,7 @@ import kotlinx.coroutines.flow.flowOn
import java.awt.Component import java.awt.Component
import java.nio.file.Files import java.nio.file.Files
import java.nio.file.Path import java.nio.file.Path
import java.util.UUID import java.util.*
import kotlin.io.path.isDirectory import kotlin.io.path.isDirectory
import kotlin.io.path.isExecutable import kotlin.io.path.isExecutable
import kotlin.io.path.isRegularFile import kotlin.io.path.isRegularFile
@ -74,10 +67,6 @@ sealed interface ZLSDriver: UUIDComboBoxDriver<ZLSVersion> {
return ZLSComboBox(model) return ZLSComboBox(model)
} }
override fun createNamedConfigurable(uuid: UUID, elem: ZLSVersion): NamedConfigurable<UUID> {
return ZLSConfigurable(uuid, elem)
}
override suspend fun resolvePseudo( override suspend fun resolvePseudo(
context: Component, context: Component,
elem: ListElem.Pseudo<ZLSVersion> elem: ListElem.Pseudo<ZLSVersion>
@ -100,6 +89,10 @@ sealed interface ZLSDriver: UUIDComboBoxDriver<ZLSVersion> {
return res return res
} }
override fun createNamedConfigurable(uuid: UUID, elem: ZLSVersion): NamedConfigurable<UUID> {
return ZLSConfigurable(uuid, elem, false)
}
override val data: ZigProjectConfigurationProvider.IUserDataBridge? override val data: ZigProjectConfigurationProvider.IUserDataBridge?
get() = null get() = null
} }
@ -120,6 +113,10 @@ sealed interface ZLSDriver: UUIDComboBoxDriver<ZLSVersion> {
res.add(suggestZLSVersions(project, data, toolchainVersion).asPending()) res.add(suggestZLSVersions(project, data, toolchainVersion).asPending())
return res return res
} }
override fun createNamedConfigurable(uuid: UUID, elem: ZLSVersion): NamedConfigurable<UUID> {
return ZLSConfigurable(uuid, elem, true)
}
} }
} }
@ -149,16 +146,16 @@ private fun suggestZLSVersions(project: Project? = null, data: ZigProjectConfigu
emitIfCompatible(path, toolchainVersion) emitIfCompatible(path, toolchainVersion)
} }
val exe = if (SystemInfo.isWindows) "zls.exe" else "zls" val exe = if (SystemInfo.isWindows) "zls.exe" else "zls"
getWellKnownZLS().forEach { wellKnown -> wellKnownZLS.forEach { wellKnown ->
runCatching { runCatching {
Files.newDirectoryStream(wellKnown).use { stream -> Files.newDirectoryStream(wellKnown).use { stream ->
stream.asSequence().filterNotNull().forEach { dir -> stream.asSequence().filterNotNull().forEach streamForEach@{ dir ->
val path = dir.resolve(exe) val path = dir.resolve(exe)
if (!path.isRegularFile() || !path.isExecutable()) { if (!path.isRegularFile() || !path.isExecutable()) {
return@forEach return@streamForEach
} }
if (existing.any { it.path == path }) { if (existing.any { it.path == path }) {
return@forEach return@streamForEach
} }
emitIfCompatible(path, toolchainVersion) emitIfCompatible(path, toolchainVersion)
} }
@ -195,8 +192,8 @@ private fun numericVersionEquals(a: SemVer, b: SemVer): Boolean {
} }
fun getSuggestedZLSPath(): Path? { val suggestedZLSPath: Path? by lazy {
return getWellKnownZLS().getOrNull(0) wellKnownZLS.getOrNull(0)
} }
/** /**
@ -212,17 +209,9 @@ fun getSuggestedZLSPath(): Path? {
* *
* and HOME is the user home path * and HOME is the user home path
*/ */
private fun getWellKnownZLS(): List<Path> { private val wellKnownZLS: List<Path> by lazy {
val home = System.getProperty("user.home")?.toNioPathOrNull() ?: return emptyList()
val xdgDataHome = when(OS.CURRENT) {
OS.macOS -> home.resolve("Library")
OS.Windows -> System.getenv("LOCALAPPDATA")?.toNioPathOrNull()
else -> System.getenv("XDG_DATA_HOME")?.toNioPathOrNull() ?: home.resolve(Path.of(".local", "share"))
}
val res = ArrayList<Path>() val res = ArrayList<Path>()
if (xdgDataHome != null && xdgDataHome.isDirectory()) { xdgDataHome?.let { res.add(it.resolve("zls")) }
res.add(xdgDataHome.resolve("zls")) homePath?.let { res.add(it.resolve(".zls")) }
} res
res.add(home.resolve(".zls"))
return res
} }

View file

@ -22,8 +22,6 @@
package com.falsepattern.zigbrains.lsp.zls.ui package com.falsepattern.zigbrains.lsp.zls.ui
import com.falsepattern.zigbrains.lsp.ZLSStarter
import com.falsepattern.zigbrains.lsp.startLSP
import com.falsepattern.zigbrains.lsp.zls.ZLSVersion import com.falsepattern.zigbrains.lsp.zls.ZLSVersion
import com.falsepattern.zigbrains.lsp.zls.withZLS import com.falsepattern.zigbrains.lsp.zls.withZLS
import com.falsepattern.zigbrains.lsp.zls.zlsUUID import com.falsepattern.zigbrains.lsp.zls.zlsUUID
@ -57,19 +55,21 @@ class ZLSEditor<T: ZigToolchain>(private val sharedState: ZigProjectConfiguratio
} }
} }
override fun isModified(toolchain: T): Boolean { override fun isModified(elem: T): Boolean {
return toolchain.zlsUUID != selectedUUID if (isEmpty)
return false
return elem.zlsUUID != selectedUUID
} }
override fun apply(toolchain: T): T { override fun apply(elem: T): T {
return toolchain.withZLS(selectedUUID) return elem.withZLS(selectedUUID)
} }
override fun reset(toolchain: T?) { override fun reset(elem: T?) {
selectedUUID = toolchain?.zlsUUID selectedUUID = elem?.zlsUUID
zigCoroutineScope.launch { zigCoroutineScope.launch {
listChanged() listChanged()
selectedUUID = toolchain?.zlsUUID selectedUUID = elem?.zlsUUID
} }
} }

View file

@ -25,12 +25,7 @@ package com.falsepattern.zigbrains.lsp.zls.ui
import com.falsepattern.zigbrains.lsp.LSPIcons import com.falsepattern.zigbrains.lsp.LSPIcons
import com.falsepattern.zigbrains.lsp.ZLSBundle import com.falsepattern.zigbrains.lsp.ZLSBundle
import com.falsepattern.zigbrains.lsp.zls.ZLSVersion import com.falsepattern.zigbrains.lsp.zls.ZLSVersion
import com.falsepattern.zigbrains.shared.ui.ListElem import com.falsepattern.zigbrains.shared.ui.*
import com.falsepattern.zigbrains.shared.ui.ZBCellRenderer
import com.falsepattern.zigbrains.shared.ui.ZBComboBox
import com.falsepattern.zigbrains.shared.ui.ZBContext
import com.falsepattern.zigbrains.shared.ui.ZBModel
import com.falsepattern.zigbrains.shared.ui.renderPathNameComponent
import com.intellij.icons.AllIcons import com.intellij.icons.AllIcons
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.ui.SimpleTextAttributes import com.intellij.ui.SimpleTextAttributes

View file

@ -1,14 +1,12 @@
settings.group.title=ZLS Settings
settings.zls-path.label=Executable path
settings.zls-path.tooltip=Path to the ZLS Binary
settings.zls-path.browse.title=Path to the ZLS Binary
settings.zls-version.label=Detected ZLS version
settings.zls-config-path.label=Config path settings.zls-config-path.label=Config path
settings.zls-config-path.tooltip=Leave empty to use built-in config generated from the settings below settings.zls-config-path.tooltip=Leave empty to use built-in config generated from the settings below
settings.zls-config-path.browse.title=Path to the Custom ZLS Config File (Optional) settings.zls-config-path.browse.title=Path to the Custom ZLS Config File (Optional)
settings.inlay-hints-group.label=Inlay Hints settings.inlay-hints-group.label=Inlay Hints
settings.inlay-hints-enable.label=Enable settings.inlay-hints-enable.label=Enable
settings.inlay-hints-enable.tooltip=Toggle this to enable/disable all inlay hints settings.inlay-hints-enable.tooltip=Toggle this to enable/disable all inlay hints
settings.inlay-hints-max-size.label=Maximum Size
settings.inlay-hints-max-size.tooltip=The maximum size of a zig file to show inlay hints for.\nInlay hints in very large files make the IDE lag.\nSet to 0 to disable.
settings.inlay-hints-max-size.unit=KB
settings.enable_snippets.label=Enable snippets settings.enable_snippets.label=Enable snippets
settings.enable_snippets.tooltip=Enables snippet completions when the client also supports them settings.enable_snippets.tooltip=Enables snippet completions when the client also supports them
settings.enable_argument_placeholders.label=Enable argument placeholders settings.enable_argument_placeholders.label=Enable argument placeholders
@ -50,8 +48,6 @@ settings.build_runner_path.tooltip=Specify a custom build runner to resolve buil
settings.global_cache_path.label=Global cache path settings.global_cache_path.label=Global cache path
settings.global_cache_path.tooltip=Path to a directory that will be used as zig's cache. Will default to `${KnownFolders.Cache}/zls`. settings.global_cache_path.tooltip=Path to a directory that will be used as zig's cache. Will default to `${KnownFolders.Cache}/zls`.
notification.group.zigbrains-lsp=ZigBrains LSP Integration notification.group.zigbrains-lsp=ZigBrains LSP Integration
notification.message.could-not-detect.content=Could not detect ZLS binary, please configure it
notification.message.zls-exe-path-invalid.content=ZLS executable path could not be parsed: {0}
notification.message.zls-exe-not-exists.content=ZLS executable does not exist: {0} notification.message.zls-exe-not-exists.content=ZLS executable does not exist: {0}
notification.message.zls-exe-not-executable.content=ZLS executable is not an executable file: {0} notification.message.zls-exe-not-executable.content=ZLS executable is not an executable file: {0}
notification.message.zls-config-not-exists.content=ZLS config file does not exist: {0} notification.message.zls-config-not-exists.content=ZLS config file does not exist: {0}
@ -61,7 +57,6 @@ notification.message.zls-config-autogen-failed.content=Failed to autogenerate ZL
notification.banner.zls-not-running=Zig Language Server is not running. Check the [Language Servers] tool menu! notification.banner.zls-not-running=Zig Language Server is not running. Check the [Language Servers] tool menu!
notification.banner.zls-bad-config=Zig Language Server is misconfigured. Check [Settings | Languages \\& Frameworks | Zig]! notification.banner.zls-bad-config=Zig Language Server is misconfigured. Check [Settings | Languages \\& Frameworks | Zig]!
progress.title.create-connection-provider=Creating ZLS connection provider progress.title.create-connection-provider=Creating ZLS connection provider
progress.title.validate=Validating ZLS
# suppress inspection "UnusedProperty" # suppress inspection "UnusedProperty"
lsp.zls.name=Zig Language Server lsp.zls.name=Zig Language Server
# suppress inspection "UnusedProperty" # suppress inspection "UnusedProperty"
@ -73,3 +68,15 @@ settings.model.none.text=<No ZLS>
settings.model.loading.text=Loading\u2026 settings.model.loading.text=Loading\u2026
settings.model.from-disk.text=Add ZLS from disk\u2026 settings.model.from-disk.text=Add ZLS from disk\u2026
settings.model.download.text=Download ZLS\u2026 settings.model.download.text=Download ZLS\u2026
settings.downloader.title=Install ZLS
settings.downloader.progress.fetch=Fetching ZLS version information
settings.downloader.progress.install=Installing ZLS {}
settings.downloader.service.index=ZLS version information
settings.local-selector.title=Select ZLS from disk
settings.local-selector.chooser.title=ZLS Binary
settings.local-selector.state.invalid=Invalid ZLS path
settings.local-selector.state.ok=ZLS path OK
dialog.title.zls=Path to the ZLS Executable
settings.panel.path.label=Path:
settings.panel.version.label=Version:
settings.panel.settings.group.label=Settings:

View file

@ -23,8 +23,6 @@
set -e set -e
declare -a branches=("dev" "master" "242" "241")
die () { die () {
echo >&2 "$@" echo >&2 "$@"
exit 1 exit 1
@ -32,8 +30,4 @@ die () {
[ "$#" -eq 1 ] || die "1 argument required, $# provided" [ "$#" -eq 1 ] || die "1 argument required, $# provided"
for i in "${branches[@]}" git push --atomic "$1" "dev" "master" "243" "242" "241"
do
echo "Pushing branch $i"
git push "$1" "$i"
done

View file

@ -4,7 +4,7 @@
<vendor>FalsePattern</vendor> <vendor>FalsePattern</vendor>
<depends config-file="zigbrains-core.xml">com.intellij.modules.platform</depends> <depends config-file="zigbrains-core.xml">com.intellij.modules.platform</depends>
<depends config-file="zigbrains-lsp.xml" optional="true">com.redhat.devtools.lsp4ij</depends> <depends config-file="zigbrains-lsp.xml">com.redhat.devtools.lsp4ij</depends>
<depends config-file="zigbrains-debugger.xml" optional="true">com.intellij.modules.cidr.debugger</depends> <depends config-file="zigbrains-debugger.xml" optional="true">com.intellij.modules.cidr.debugger</depends>
<depends config-file="zigbrains-cidr.xml" optional="true">com.intellij.cidr.base</depends> <depends config-file="zigbrains-cidr.xml" optional="true">com.intellij.cidr.base</depends>
<depends config-file="zigbrains-clion.xml" optional="true">com.intellij.clion</depends> <depends config-file="zigbrains-clion.xml" optional="true">com.intellij.clion</depends>