local zig toolchain name, edit button state, sorted recommends
This commit is contained in:
parent
a8f97172d6
commit
54cd514249
7 changed files with 79 additions and 42 deletions
|
@ -25,9 +25,9 @@ package com.falsepattern.zigbrains.project.toolchain.base
|
||||||
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainListService
|
import com.falsepattern.zigbrains.project.toolchain.ZigToolchainListService
|
||||||
import com.intellij.openapi.extensions.ExtensionPointName
|
import com.intellij.openapi.extensions.ExtensionPointName
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.ui.NamedConfigurable
|
|
||||||
import com.intellij.openapi.util.UserDataHolder
|
import com.intellij.openapi.util.UserDataHolder
|
||||||
import com.intellij.ui.SimpleColoredComponent
|
import com.intellij.ui.SimpleColoredComponent
|
||||||
|
import com.intellij.util.text.SemVer
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
|
|
||||||
private val EXTENSION_POINT_NAME = ExtensionPointName.create<ZigToolchainProvider>("com.falsepattern.zigbrains.toolchainProvider")
|
private val EXTENSION_POINT_NAME = ExtensionPointName.create<ZigToolchainProvider>("com.falsepattern.zigbrains.toolchainProvider")
|
||||||
|
@ -41,7 +41,7 @@ internal interface ZigToolchainProvider {
|
||||||
fun serialize(toolchain: ZigToolchain): Map<String, String>
|
fun serialize(toolchain: ZigToolchain): Map<String, String>
|
||||||
fun matchesSuggestion(toolchain: ZigToolchain, suggestion: ZigToolchain): Boolean
|
fun matchesSuggestion(toolchain: ZigToolchain, suggestion: ZigToolchain): Boolean
|
||||||
fun createConfigurable(uuid: UUID, toolchain: ZigToolchain): ZigToolchainConfigurable<*>
|
fun createConfigurable(uuid: UUID, toolchain: ZigToolchain): ZigToolchainConfigurable<*>
|
||||||
fun suggestToolchains(): List<ZigToolchain>
|
fun suggestToolchains(): List<Pair<SemVer?, ZigToolchain>>
|
||||||
fun render(toolchain: ZigToolchain, component: SimpleColoredComponent, isSuggestion: Boolean)
|
fun render(toolchain: ZigToolchain, component: SimpleColoredComponent, isSuggestion: Boolean)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,8 +71,8 @@ fun suggestZigToolchains(): List<ZigToolchain> {
|
||||||
return EXTENSION_POINT_NAME.extensionList.flatMap { ext ->
|
return EXTENSION_POINT_NAME.extensionList.flatMap { ext ->
|
||||||
val compatibleExisting = existing.filter { ext.isCompatible(it) }
|
val compatibleExisting = existing.filter { ext.isCompatible(it) }
|
||||||
val suggestions = ext.suggestToolchains()
|
val suggestions = ext.suggestToolchains()
|
||||||
suggestions.filter { suggestion -> compatibleExisting.none { existing -> ext.matchesSuggestion(existing, suggestion) } }
|
suggestions.filter { suggestion -> compatibleExisting.none { existing -> ext.matchesSuggestion(existing, suggestion.second) } }
|
||||||
}
|
}.sortedByDescending { it.first }.map { it.second }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ZigToolchain.render(component: SimpleColoredComponent, isSuggestion: Boolean) {
|
fun ZigToolchain.render(component: SimpleColoredComponent, isSuggestion: Boolean) {
|
||||||
|
|
|
@ -74,7 +74,7 @@ object Downloader {
|
||||||
) {
|
) {
|
||||||
version.downloadAndUnpack(downloadPath)
|
version.downloadAndUnpack(downloadPath)
|
||||||
}
|
}
|
||||||
return LocalZigToolchain.tryFromPath(downloadPath)
|
return LocalZigToolchain.tryFromPath(downloadPath)?.second
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresEdt
|
@RequiresEdt
|
||||||
|
|
|
@ -30,11 +30,13 @@ import com.falsepattern.zigbrains.project.toolchain.local.LocalZigToolchain
|
||||||
import com.falsepattern.zigbrains.shared.coroutine.asContextElement
|
import com.falsepattern.zigbrains.shared.coroutine.asContextElement
|
||||||
import com.falsepattern.zigbrains.shared.coroutine.runInterruptibleEDT
|
import com.falsepattern.zigbrains.shared.coroutine.runInterruptibleEDT
|
||||||
import com.intellij.icons.AllIcons
|
import com.intellij.icons.AllIcons
|
||||||
|
import com.intellij.openapi.fileChooser.FileChooser
|
||||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
|
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory
|
||||||
import com.intellij.openapi.ui.DialogBuilder
|
import com.intellij.openapi.ui.DialogBuilder
|
||||||
import com.intellij.openapi.util.Disposer
|
import com.intellij.openapi.util.Disposer
|
||||||
import com.intellij.ui.DocumentAdapter
|
import com.intellij.ui.DocumentAdapter
|
||||||
import com.intellij.ui.components.JBLabel
|
import com.intellij.ui.components.JBLabel
|
||||||
|
import com.intellij.ui.components.JBTextField
|
||||||
import com.intellij.ui.components.textFieldWithBrowseButton
|
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
|
||||||
|
@ -52,17 +54,16 @@ object LocalSelector {
|
||||||
@RequiresEdt
|
@RequiresEdt
|
||||||
private fun doBrowseFromDisk(): ZigToolchain? {
|
private fun doBrowseFromDisk(): ZigToolchain? {
|
||||||
val dialog = DialogBuilder()
|
val dialog = DialogBuilder()
|
||||||
|
val name = JBTextField().also { it.columns = 25 }
|
||||||
val path = textFieldWithBrowseButton(
|
val path = textFieldWithBrowseButton(
|
||||||
null,
|
null,
|
||||||
FileChooserDescriptorFactory.createSingleFolderDescriptor()
|
FileChooserDescriptorFactory.createSingleFolderDescriptor()
|
||||||
.withTitle(ZigBrainsBundle.message("settings.toolchain.local-selector.chooser.title"))
|
.withTitle(ZigBrainsBundle.message("settings.toolchain.local-selector.chooser.title"))
|
||||||
)
|
)
|
||||||
Disposer.register(dialog, path)
|
Disposer.register(dialog, path)
|
||||||
path.textField.columns = 50
|
|
||||||
lateinit var errorMessageBox: JBLabel
|
lateinit var errorMessageBox: JBLabel
|
||||||
path.addDocumentListener(object: DocumentAdapter() {
|
fun verify(path: String) {
|
||||||
override fun textChanged(e: DocumentEvent) {
|
val tc = LocalZigToolchain.tryFromPathString(path)?.second
|
||||||
val tc = LocalZigToolchain.tryFromPathString(path.text)
|
|
||||||
if (tc == null) {
|
if (tc == null) {
|
||||||
errorMessageBox.icon = AllIcons.General.Error
|
errorMessageBox.icon = AllIcons.General.Error
|
||||||
errorMessageBox.text = ZigBrainsBundle.message("settings.toolchain.local-selector.state.invalid")
|
errorMessageBox.text = ZigBrainsBundle.message("settings.toolchain.local-selector.state.invalid")
|
||||||
|
@ -78,13 +79,25 @@ object LocalSelector {
|
||||||
?: ZigBrainsBundle.message("settings.toolchain.local-selector.state.already-exists-unnamed")
|
?: ZigBrainsBundle.message("settings.toolchain.local-selector.state.already-exists-unnamed")
|
||||||
dialog.setOkActionEnabled(true)
|
dialog.setOkActionEnabled(true)
|
||||||
} else {
|
} else {
|
||||||
errorMessageBox.icon = Icons.Zig
|
errorMessageBox.icon = AllIcons.General.Information
|
||||||
errorMessageBox.text = tc.name ?: ZigBrainsBundle.message("settings.toolchain.local-selector.state.ok")
|
errorMessageBox.text = ZigBrainsBundle.message("settings.toolchain.local-selector.state.ok")
|
||||||
dialog.setOkActionEnabled(true)
|
dialog.setOkActionEnabled(true)
|
||||||
}
|
}
|
||||||
|
val prevNameDefault = name.emptyText.text.trim() == name.text.trim() || name.text.isBlank()
|
||||||
|
name.emptyText.text = tc?.name ?: ""
|
||||||
|
if (prevNameDefault) {
|
||||||
|
name.text = name.emptyText.text
|
||||||
|
}
|
||||||
|
}
|
||||||
|
path.addDocumentListener(object: DocumentAdapter() {
|
||||||
|
override fun textChanged(e: DocumentEvent) {
|
||||||
|
verify(path.text)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
val center = panel {
|
val center = panel {
|
||||||
|
row(ZigBrainsBundle.message("settings.toolchain.local-selector.name.label")) {
|
||||||
|
cell(name).resizableColumn().align(AlignX.FILL)
|
||||||
|
}
|
||||||
row(ZigBrainsBundle.message("settings.toolchain.local-selector.path.label")) {
|
row(ZigBrainsBundle.message("settings.toolchain.local-selector.path.label")) {
|
||||||
cell(path).resizableColumn().align(AlignX.FILL)
|
cell(path).resizableColumn().align(AlignX.FILL)
|
||||||
}
|
}
|
||||||
|
@ -97,9 +110,19 @@ object LocalSelector {
|
||||||
dialog.setTitle(ZigBrainsBundle.message("settings.toolchain.local-selector.title"))
|
dialog.setTitle(ZigBrainsBundle.message("settings.toolchain.local-selector.title"))
|
||||||
dialog.addCancelAction()
|
dialog.addCancelAction()
|
||||||
dialog.addOkAction().also { it.setText(ZigBrainsBundle.message("settings.toolchain.local-selector.ok-action")) }
|
dialog.addOkAction().also { it.setText(ZigBrainsBundle.message("settings.toolchain.local-selector.ok-action")) }
|
||||||
|
val chosenFile = FileChooser.chooseFile(
|
||||||
|
FileChooserDescriptorFactory.createSingleFolderDescriptor()
|
||||||
|
.withTitle(ZigBrainsBundle.message("settings.toolchain.local-selector.chooser.title")),
|
||||||
|
null,
|
||||||
|
null
|
||||||
|
)
|
||||||
|
if (chosenFile != null) {
|
||||||
|
verify(chosenFile.path)
|
||||||
|
path.text = chosenFile.path
|
||||||
|
}
|
||||||
if (!dialog.showAndGet()) {
|
if (!dialog.showAndGet()) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return LocalZigToolchain.tryFromPathString(path.text)
|
return LocalZigToolchain.tryFromPathString(path.text)?.second?.also { it.copy(name = name.text.ifBlank { null } ?: it.name) }
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -32,6 +32,7 @@ import com.intellij.openapi.util.KeyWithDefaultValue
|
||||||
import com.intellij.openapi.util.SystemInfo
|
import com.intellij.openapi.util.SystemInfo
|
||||||
import com.intellij.openapi.util.io.toNioPathOrNull
|
import com.intellij.openapi.util.io.toNioPathOrNull
|
||||||
import com.intellij.openapi.vfs.toNioPathOrNull
|
import com.intellij.openapi.vfs.toNioPathOrNull
|
||||||
|
import com.intellij.util.text.SemVer
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
|
||||||
@JvmRecord
|
@JvmRecord
|
||||||
|
@ -66,22 +67,27 @@ data class LocalZigToolchain(val location: Path, val std: Path? = null, override
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun tryFromPathString(pathStr: String?): LocalZigToolchain? {
|
fun tryFromPathString(pathStr: String?): Pair<SemVer?, LocalZigToolchain>? {
|
||||||
return pathStr?.ifBlank { null }?.toNioPathOrNull()?.let(::tryFromPath)
|
return pathStr?.ifBlank { null }?.toNioPathOrNull()?.let(::tryFromPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun tryFromPath(path: Path): LocalZigToolchain? {
|
fun tryFromPath(path: Path): Pair<SemVer?, LocalZigToolchain>? {
|
||||||
var tc = LocalZigToolchain(path)
|
var tc = LocalZigToolchain(path)
|
||||||
if (!tc.zig.fileValid()) {
|
if (!tc.zig.fileValid()) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
tc.zig
|
val versionStr = tc.zig
|
||||||
.getEnvBlocking(null)
|
.getEnvBlocking(null)
|
||||||
.getOrNull()
|
.getOrNull()
|
||||||
?.version
|
?.version
|
||||||
?.let { "Zig $it" }
|
val version: SemVer?
|
||||||
?.let { tc = tc.copy(name = it) }
|
if (versionStr != null) {
|
||||||
return tc
|
version = SemVer.parseFromText(versionStr)
|
||||||
|
tc = tc.copy(name = "Zig $versionStr")
|
||||||
|
} else {
|
||||||
|
version = null
|
||||||
|
}
|
||||||
|
return version to tc
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -37,6 +37,7 @@ import com.intellij.ui.SimpleColoredComponent
|
||||||
import com.intellij.ui.SimpleTextAttributes
|
import com.intellij.ui.SimpleTextAttributes
|
||||||
import com.intellij.util.EnvironmentUtil
|
import com.intellij.util.EnvironmentUtil
|
||||||
import com.intellij.util.system.OS
|
import com.intellij.util.system.OS
|
||||||
|
import com.intellij.util.text.SemVer
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.file.Files
|
import java.nio.file.Files
|
||||||
import java.nio.file.Path
|
import java.nio.file.Path
|
||||||
|
@ -97,7 +98,7 @@ class LocalZigToolchainProvider: ZigToolchainProvider {
|
||||||
return LocalZigToolchainConfigurable(uuid, toolchain)
|
return LocalZigToolchainConfigurable(uuid, toolchain)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun suggestToolchains(): List<ZigToolchain> {
|
override fun suggestToolchains(): List<Pair<SemVer?, ZigToolchain>> {
|
||||||
val res = HashSet<String>()
|
val res = HashSet<String>()
|
||||||
EnvironmentUtil.getValue("PATH")?.split(File.pathSeparatorChar)?.let { res.addAll(it.toList()) }
|
EnvironmentUtil.getValue("PATH")?.split(File.pathSeparatorChar)?.let { res.addAll(it.toList()) }
|
||||||
val wellKnown = getWellKnown()
|
val wellKnown = getWellKnown()
|
||||||
|
|
|
@ -52,7 +52,7 @@ class ZigToolchainEditor(private val isForDefaultProject: Boolean = false): SubC
|
||||||
private val toolchainBox: TCComboBox
|
private val toolchainBox: TCComboBox
|
||||||
private var selectOnNextReload: UUID? = null
|
private var selectOnNextReload: UUID? = null
|
||||||
private val model: TCModel
|
private val model: TCModel
|
||||||
private lateinit var editButton: JButton
|
private var editButton: JButton? = null
|
||||||
init {
|
init {
|
||||||
model = TCModel(getModelList())
|
model = TCModel(getModelList())
|
||||||
toolchainBox = TCComboBox(model)
|
toolchainBox = TCComboBox(model)
|
||||||
|
@ -60,15 +60,21 @@ class ZigToolchainEditor(private val isForDefaultProject: Boolean = false): SubC
|
||||||
ZigToolchainListService.getInstance().addChangeListener(this)
|
ZigToolchainListService.getInstance().addChangeListener(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun refreshButtonState(item: Any?) {
|
||||||
|
editButton?.isEnabled = item is TCListElem.Toolchain.Actual
|
||||||
|
editButton?.repaint()
|
||||||
|
}
|
||||||
|
|
||||||
private fun itemStateChanged(event: ItemEvent) {
|
private fun itemStateChanged(event: ItemEvent) {
|
||||||
if (event.stateChange != ItemEvent.SELECTED) {
|
if (event.stateChange != ItemEvent.SELECTED) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val item = event.item
|
val item = event.item
|
||||||
|
refreshButtonState(item)
|
||||||
if (item !is TCListElem.Pseudo)
|
if (item !is TCListElem.Pseudo)
|
||||||
return
|
return
|
||||||
zigCoroutineScope.launch(toolchainBox.asContextElement()) {
|
zigCoroutineScope.launch(toolchainBox.asContextElement()) {
|
||||||
val uuid = ZigToolchainComboBoxHandler.onItemSelected(toolchainBox, item)
|
val uuid = runCatching { ZigToolchainComboBoxHandler.onItemSelected(toolchainBox, item) }.getOrNull()
|
||||||
withEDTContext(toolchainBox.asContextElement()) {
|
withEDTContext(toolchainBox.asContextElement()) {
|
||||||
applyUUIDNowOrOnReload(uuid)
|
applyUUIDNowOrOnReload(uuid)
|
||||||
}
|
}
|
||||||
|
@ -105,10 +111,6 @@ class ZigToolchainEditor(private val isForDefaultProject: Boolean = false): SubC
|
||||||
}
|
}
|
||||||
model.selectedItem = TCListElem.None
|
model.selectedItem = TCListElem.None
|
||||||
}
|
}
|
||||||
withContext(Dispatchers.EDT + editButton.asContextElement()) {
|
|
||||||
editButton.isEnabled = model.selectedItem is TCListElem.Toolchain.Actual
|
|
||||||
editButton.repaint()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun attach(p: Panel): Unit = with(p) {
|
override fun attach(p: Panel): Unit = with(p) {
|
||||||
|
@ -129,7 +131,10 @@ class ZigToolchainEditor(private val isForDefaultProject: Boolean = false): SubC
|
||||||
applyUUIDNowOrOnReload(selectedUUID)
|
applyUUIDNowOrOnReload(selectedUUID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.component.let { editButton = it }
|
}.component.let {
|
||||||
|
editButton = it
|
||||||
|
refreshButtonState(toolchainBox.selectedItem)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,6 +159,7 @@ class ZigToolchainEditor(private val isForDefaultProject: Boolean = false): SubC
|
||||||
override fun reset(context: Project?) {
|
override fun reset(context: Project?) {
|
||||||
val project = context ?: ProjectManager.getInstance().defaultProject
|
val project = context ?: ProjectManager.getInstance().defaultProject
|
||||||
toolchainBox.selectedToolchain = ZigToolchainService.getInstance(project).toolchainUUID
|
toolchainBox.selectedToolchain = ZigToolchainService.getInstance(project).toolchainUUID
|
||||||
|
refreshButtonState(toolchainBox.selectedItem)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
|
|
|
@ -143,10 +143,11 @@ settings.toolchain.downloader.archive-size.text=Archive size: {0}
|
||||||
settings.toolchain.downloader.service.index=Zig version information
|
settings.toolchain.downloader.service.index=Zig version information
|
||||||
settings.toolchain.downloader.service.tarball=Zig archive
|
settings.toolchain.downloader.service.tarball=Zig archive
|
||||||
settings.toolchain.local-selector.title=Select Zig From Disk
|
settings.toolchain.local-selector.title=Select Zig From Disk
|
||||||
|
settings.toolchain.local-selector.name.label=Name:
|
||||||
settings.toolchain.local-selector.path.label=Path:
|
settings.toolchain.local-selector.path.label=Path:
|
||||||
settings.toolchain.local-selector.ok-action=Add
|
settings.toolchain.local-selector.ok-action=Add
|
||||||
settings.toolchain.local-selector.chooser.title=Existing Zig Install Directory
|
settings.toolchain.local-selector.chooser.title=Existing Zig Install Directory
|
||||||
settings.toolchain.local-selector.state.invalid=Invalid toolchain path
|
settings.toolchain.local-selector.state.invalid=Invalid toolchain path
|
||||||
settings.toolchain.local-selector.state.already-exists-unnamed=Toolchain already exists
|
settings.toolchain.local-selector.state.already-exists-unnamed=Toolchain already exists
|
||||||
settings.toolchain.local-selector.state.already-exists-named=Toolchain already exists as "{0}"
|
settings.toolchain.local-selector.state.already-exists-named=Toolchain already exists as "{0}"
|
||||||
settings.toolchain.local-selector.state.ok=OK
|
settings.toolchain.local-selector.state.ok=Toolchain path OK
|
||||||
|
|
Loading…
Add table
Reference in a new issue