backport: 24.0.0
This commit is contained in:
parent
de68e65d7a
commit
639cce4e3c
30 changed files with 179 additions and 209 deletions
24
CHANGELOG.md
24
CHANGELOG.md
|
@ -17,6 +17,30 @@ Changelog structure reference:
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
## [24.0.0]
|
||||
|
||||
### Added
|
||||
|
||||
- Project, Debugging
|
||||
- TTY support for zig processes
|
||||
|
||||
### Removed
|
||||
|
||||
- Project
|
||||
- "Emulate terminal" and "colored output" config options have been removed from zig run/test/build tasks, as they are no longer required for ZigBrains to work.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Debugger
|
||||
- Build errors didn't get shown in the console
|
||||
|
||||
- Project
|
||||
- File path browse buttons in zig run configurations didn't work
|
||||
- Occasional GUI deadlocks
|
||||
|
||||
- Zig
|
||||
- IPC wrapper wasn't passing exit code
|
||||
|
||||
## [23.1.2]
|
||||
|
||||
### Fixed
|
||||
|
|
|
@ -57,8 +57,8 @@ class ZigClionDebuggerDriverConfigurationProvider: ZigDebuggerDriverConfiguratio
|
|||
}
|
||||
return when(toolchain.debuggerKind) {
|
||||
CPPDebugger.Kind.BUNDLED_GDB,
|
||||
CPPDebugger.Kind.CUSTOM_GDB -> CLionGDBDriverConfiguration(project, toolchain)
|
||||
CPPDebugger.Kind.BUNDLED_LLDB -> CLionLLDBDriverConfiguration(project, toolchain)
|
||||
CPPDebugger.Kind.CUSTOM_GDB -> CLionGDBDriverConfiguration(project, toolchain, isEmulateTerminal = emulateTerminal)
|
||||
CPPDebugger.Kind.BUNDLED_LLDB -> CLionLLDBDriverConfiguration(project, toolchain, isEmulateTerminal = emulateTerminal)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,9 +22,10 @@
|
|||
|
||||
package com.falsepattern.zigbrains.debugger
|
||||
|
||||
import com.intellij.execution.filters.Filter
|
||||
import com.intellij.execution.filters.TextConsoleBuilder
|
||||
import com.intellij.xdebugger.XDebugSession
|
||||
import com.jetbrains.cidr.execution.RunParameters
|
||||
import com.jetbrains.cidr.execution.debugger.CidrLocalDebugProcess
|
||||
|
||||
class ZigLocalDebugProcess(parameters: RunParameters, session: XDebugSession, consoleBuilder: TextConsoleBuilder) : CidrLocalDebugProcess(parameters, session, consoleBuilder)
|
||||
class ZigLocalDebugProcess(parameters: RunParameters, session: XDebugSession, consoleBuilder: TextConsoleBuilder) : CidrLocalDebugProcess(parameters, session, consoleBuilder, { Filter.EMPTY_ARRAY }, true)
|
|
@ -23,6 +23,7 @@
|
|||
package com.falsepattern.zigbrains.debugger.runner.base
|
||||
|
||||
import com.falsepattern.zigbrains.project.run.ZigProcessHandler
|
||||
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
|
||||
|
@ -48,12 +49,7 @@ class PreLaunchProcessListener(val console: ConsoleView) : ProcessListener {
|
|||
@Throws(ExecutionException::class)
|
||||
suspend fun executeCommandLineWithHook(project: Project, commandLine: GeneralCommandLine): Boolean {
|
||||
return withProgressText(commandLine.commandLineString) {
|
||||
val ipc = IPCUtil.wrapWithIPC(commandLine)
|
||||
val cli = ipc?.cli ?: commandLine
|
||||
val processHandler = ZigProcessHandler(cli)
|
||||
if (ipc != null) {
|
||||
project.ipc?.launchWatcher(ipc, processHandler.process)
|
||||
}
|
||||
val processHandler = commandLine.startIPCAwareProcess(project)
|
||||
this@PreLaunchProcessListener.processHandler = processHandler
|
||||
hook(processHandler)
|
||||
processHandler.startNotify()
|
||||
|
@ -74,10 +70,6 @@ class PreLaunchProcessListener(val console: ConsoleView) : ProcessListener {
|
|||
|
||||
override fun processTerminated(event: ProcessEvent) {
|
||||
if (event.exitCode != 0) {
|
||||
console.print(
|
||||
"Process finished with exit code " + event.exitCode,
|
||||
ConsoleViewContentType.NORMAL_OUTPUT
|
||||
)
|
||||
isBuildFailed = true
|
||||
} else {
|
||||
isBuildFailed = false
|
||||
|
|
|
@ -26,6 +26,7 @@ import com.falsepattern.zigbrains.project.execution.base.ZigProfileState
|
|||
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain
|
||||
import com.falsepattern.zigbrains.shared.zigCoroutineScope
|
||||
import com.intellij.execution.configurations.GeneralCommandLine
|
||||
import com.intellij.execution.configurations.PtyCommandLine
|
||||
import com.jetbrains.cidr.execution.Installer
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.future.asCompletableFuture
|
||||
|
@ -39,7 +40,7 @@ class ZigDebugEmitBinaryInstaller<ProfileState: ZigProfileState<*>>(
|
|||
): Installer {
|
||||
override fun install(): GeneralCommandLine {
|
||||
val cfg = profileState.configuration
|
||||
val cli = GeneralCommandLine().withExePath(executableFile.absolutePath)
|
||||
val cli = PtyCommandLine().withConsoleMode(false).withExePath(executableFile.absolutePath)
|
||||
cfg.workingDirectory.path?.let { x -> cli.withWorkingDirectory(x) }
|
||||
cli.addParameters(exeArgs)
|
||||
cli.withCharset(Charsets.UTF_8)
|
||||
|
|
|
@ -58,7 +58,7 @@ abstract class ZigDebugRunnerBase<ProfileState : ZigProfileState<*>> : ZigProgra
|
|||
val project = environment.project
|
||||
val driverProviders = ZigDebuggerDriverConfigurationProviderBase.EXTENSION_POINT_NAME.extensionList
|
||||
for (provider in driverProviders) {
|
||||
val driver = provider.getDebuggerConfiguration(project, isElevated = false, emulateTerminal = false, DebuggerDriverConfiguration::class.java) ?: continue
|
||||
val driver = provider.getDebuggerConfiguration(project, isElevated = false, emulateTerminal = true, DebuggerDriverConfiguration::class.java) ?: continue
|
||||
return executeWithDriver(state, toolchain, environment, driver) ?: continue
|
||||
}
|
||||
return null
|
||||
|
@ -93,12 +93,12 @@ abstract class ZigDebugRunnerBase<ProfileState : ZigProfileState<*>> : ZigProgra
|
|||
}
|
||||
}
|
||||
}
|
||||
return@reportProgress runInterruptibleEDT {
|
||||
return@reportProgress runInterruptibleEDT(ModalityState.any()) {
|
||||
val debuggerManager = XDebuggerManager.getInstance(environment.project)
|
||||
debuggerManager.startSession(environment, object: XDebugProcessStarter() {
|
||||
override fun start(session: XDebugSession): XDebugProcess {
|
||||
val project = session.project
|
||||
val textConsoleBuilder = SharedConsoleBuilder(console)
|
||||
val textConsoleBuilder = state.consoleBuilder
|
||||
val debugProcess = ZigLocalDebugProcess(runParameters, session, textConsoleBuilder)
|
||||
ProcessTerminatedListener.attach(debugProcess.processHandler, project)
|
||||
debugProcess.start()
|
||||
|
|
|
@ -62,7 +62,7 @@ class ZigDebugParametersBuild(
|
|||
withContext(Dispatchers.IO) {
|
||||
val commandLine = profileState.getCommandLine(toolchain, true)
|
||||
if (listener.executeCommandLineWithHook(profileState.environment.project, commandLine))
|
||||
throw ExecutionException(ZigDebugBundle.message("debug.build.compile.failed.generic"))
|
||||
return@withContext
|
||||
val cfg = profileState.configuration
|
||||
val workingDir = cfg.workingDirectory.path
|
||||
val exe = profileState.configuration.exePath.path ?: run {
|
||||
|
|
|
@ -31,6 +31,7 @@ import com.falsepattern.zigbrains.shared.coroutine.launchWithEDT
|
|||
import com.falsepattern.zigbrains.shared.coroutine.runModalOrBlocking
|
||||
import com.falsepattern.zigbrains.shared.zigCoroutineScope
|
||||
import com.intellij.ide.plugins.PluginManager
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.extensions.PluginId
|
||||
import com.intellij.openapi.observable.util.whenItemSelected
|
||||
import com.intellij.openapi.ui.ComboBox
|
||||
|
@ -88,7 +89,7 @@ class ZigDebuggerToolchainConfigurableUi : ZigDebuggerUiComponent {
|
|||
row(ZigDebugBundle.message("settings.debugger.toolchain.debugger.label")) {
|
||||
comment = cell(debuggerKindComboBox)
|
||||
.comment("", DEFAULT_COMMENT_WIDTH) {
|
||||
zigCoroutineScope.launchWithEDT {
|
||||
zigCoroutineScope.launchWithEDT(ModalityState.any()) {
|
||||
withModalProgress(ModalTaskOwner.component(debuggerKindComboBox), "Downloading debugger", TaskCancellation.cancellable()) {
|
||||
downloadDebugger()
|
||||
}
|
||||
|
@ -96,7 +97,7 @@ class ZigDebuggerToolchainConfigurableUi : ZigDebuggerUiComponent {
|
|||
}
|
||||
.applyToComponent {
|
||||
whenItemSelected(null) {
|
||||
zigCoroutineScope.launchWithEDT {
|
||||
zigCoroutineScope.launchWithEDT(ModalityState.any()) {
|
||||
this@ZigDebuggerToolchainConfigurableUi.update()
|
||||
}
|
||||
}
|
||||
|
@ -111,7 +112,7 @@ class ZigDebuggerToolchainConfigurableUi : ZigDebuggerUiComponent {
|
|||
cell(useClion)
|
||||
}
|
||||
}
|
||||
zigCoroutineScope.launchWithEDT {
|
||||
zigCoroutineScope.launchWithEDT(ModalityState.any()) {
|
||||
update()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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
|
||||
|
||||
import com.intellij.execution.filters.TextConsoleBuilderImpl
|
||||
import com.intellij.execution.ui.ConsoleView
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.terminal.TerminalExecutionConsole
|
||||
import java.nio.file.Path
|
||||
|
||||
class ZigConsoleBuilder(private val project: Project, private val emulateTerminal: Boolean = false): TextConsoleBuilderImpl(project) {
|
||||
override fun createConsole(): ConsoleView {
|
||||
return if (emulateTerminal)
|
||||
TerminalExecutionConsole(project, null)
|
||||
else
|
||||
super.createConsole()
|
||||
}
|
||||
}
|
|
@ -33,11 +33,11 @@ import com.intellij.openapi.options.SettingsEditor
|
|||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.ComboBox
|
||||
import com.intellij.openapi.ui.TextBrowseFolderListener
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton
|
||||
import com.intellij.openapi.util.Disposer
|
||||
import com.intellij.openapi.util.io.toNioPathOrNull
|
||||
import com.intellij.ui.components.JBCheckBox
|
||||
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.ui.dsl.builder.panel
|
||||
|
@ -161,12 +161,11 @@ class WorkDirectoryConfigurable(@Transient override val serializedName: String)
|
|||
}
|
||||
|
||||
class WorkDirectoryConfigModule(private val serializedName: String) : PathConfigModule<WorkDirectoryConfigurable>() {
|
||||
private val field = TextFieldWithBrowseButton(
|
||||
TextBrowseFolderListener(
|
||||
FileChooserDescriptorFactory.createSingleFolderDescriptor().withTitle(ZigBrainsBundle.message("dialog.title.working-directory"))
|
||||
),
|
||||
this
|
||||
)
|
||||
private val field = textFieldWithBrowseButton(
|
||||
null,
|
||||
ZigBrainsBundle.message("dialog.title.working-directory"),
|
||||
FileChooserDescriptorFactory.createSingleFolderDescriptor().withTitle(ZigBrainsBundle.message("dialog.title.working-directory"))
|
||||
).also { Disposer.register(this, it) }
|
||||
|
||||
override var stringValue by field::text
|
||||
|
||||
|
@ -201,9 +200,10 @@ class FilePathConfigurable(
|
|||
}
|
||||
|
||||
class FilePathConfigModule(private val serializedName: String, @Nls private val label: String) : PathConfigModule<FilePathConfigurable>() {
|
||||
private val field = TextFieldWithBrowseButton(
|
||||
TextBrowseFolderListener(FileChooserDescriptorFactory.createSingleFileDescriptor()),
|
||||
this
|
||||
private val field = textFieldWithBrowseButton(
|
||||
null,
|
||||
null,
|
||||
FileChooserDescriptorFactory.createSingleFileDescriptor(),
|
||||
)
|
||||
|
||||
override var stringValue by field::text
|
||||
|
@ -274,12 +274,6 @@ open class CheckboxConfigurable(
|
|||
}
|
||||
}
|
||||
|
||||
class ColoredConfigurable(serializedName: String): CheckboxConfigurable(serializedName, ZigBrainsBundle.message("exec.option.label.colored-terminal"), true) {
|
||||
override fun clone(): ColoredConfigurable {
|
||||
return super.clone() as ColoredConfigurable
|
||||
}
|
||||
}
|
||||
|
||||
class OptimizationConfigurable(
|
||||
@Transient private val serializedName: String,
|
||||
var level: OptimizationLevel = OptimizationLevel.Debug,
|
||||
|
|
|
@ -43,8 +43,6 @@ import org.jetbrains.annotations.Nls
|
|||
abstract class ZigExecConfig<T: ZigExecConfig<T>>(project: Project, factory: ConfigurationFactory, @Nls name: String): LocatableConfigurationBase<ZigProfileState<T>>(project, factory, name) {
|
||||
var workingDirectory = WorkDirectoryConfigurable("workingDirectory").apply { path = project.guessProjectDir()?.toNioPathOrNull() }
|
||||
private set
|
||||
var pty = CheckboxConfigurable("pty", ZigBrainsBundle.message("exec.option.label.emulate-terminal"), false)
|
||||
private set
|
||||
|
||||
abstract val suggestedName: @ActionText String
|
||||
@Throws(ExecutionException::class)
|
||||
|
@ -73,17 +71,12 @@ abstract class ZigExecConfig<T: ZigExecConfig<T>>(project: Project, factory: Con
|
|||
return commandLine
|
||||
}
|
||||
|
||||
fun emulateTerminal(): Boolean {
|
||||
return pty.value
|
||||
}
|
||||
|
||||
override fun clone(): T {
|
||||
val myClone = super.clone() as ZigExecConfig<*>
|
||||
myClone.workingDirectory = workingDirectory.clone()
|
||||
myClone.pty = pty.clone()
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return myClone as T
|
||||
}
|
||||
|
||||
open fun getConfigurables(): List<ZigConfigurable<*>> = listOf(workingDirectory, pty)
|
||||
open fun getConfigurables(): List<ZigConfigurable<*>> = listOf(workingDirectory)
|
||||
}
|
|
@ -23,9 +23,11 @@
|
|||
package com.falsepattern.zigbrains.project.execution.base
|
||||
|
||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
||||
import com.falsepattern.zigbrains.project.execution.ZigConsoleBuilder
|
||||
import com.falsepattern.zigbrains.project.run.ZigProcessHandler
|
||||
import com.falsepattern.zigbrains.project.settings.zigProjectSettings
|
||||
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain
|
||||
import com.falsepattern.zigbrains.shared.cli.startIPCAwareProcess
|
||||
import com.falsepattern.zigbrains.shared.coroutine.runModalOrBlocking
|
||||
import com.falsepattern.zigbrains.shared.ipc.IPCUtil
|
||||
import com.falsepattern.zigbrains.shared.ipc.ipc
|
||||
|
@ -35,11 +37,15 @@ import com.intellij.execution.ExecutionException
|
|||
import com.intellij.execution.configurations.CommandLineState
|
||||
import com.intellij.execution.configurations.GeneralCommandLine
|
||||
import com.intellij.execution.configurations.PtyCommandLine
|
||||
import com.intellij.execution.filters.TextConsoleBuilder
|
||||
import com.intellij.execution.process.ProcessHandler
|
||||
import com.intellij.execution.process.ProcessTerminatedListener
|
||||
import com.intellij.execution.runners.ExecutionEnvironment
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.platform.ide.progress.ModalTaskOwner
|
||||
import com.intellij.terminal.TerminalExecutionConsole
|
||||
import com.intellij.util.system.OS
|
||||
import kotlin.collections.contains
|
||||
import kotlin.io.path.pathString
|
||||
|
||||
abstract class ZigProfileState<T: ZigExecConfig<T>> (
|
||||
|
@ -47,6 +53,10 @@ abstract class ZigProfileState<T: ZigExecConfig<T>> (
|
|||
val configuration: T
|
||||
): CommandLineState(environment) {
|
||||
|
||||
init {
|
||||
consoleBuilder = ZigConsoleBuilder(environment.project, true)
|
||||
}
|
||||
|
||||
@Throws(ExecutionException::class)
|
||||
override fun startProcess(): ProcessHandler {
|
||||
return runModalOrBlocking({ModalTaskOwner.project(environment.project)}, {"ZigProfileState.startProcess"}) {
|
||||
|
@ -57,7 +67,7 @@ abstract class ZigProfileState<T: ZigExecConfig<T>> (
|
|||
@Throws(ExecutionException::class)
|
||||
suspend fun startProcessSuspend(): ProcessHandler {
|
||||
val toolchain = environment.project.zigProjectSettings.state.toolchain ?: throw ExecutionException(ZigBrainsBundle.message("exception.zig-profile-state.start-process.no-toolchain"))
|
||||
return startProcess(getCommandLine(toolchain, false), environment.project)
|
||||
return getCommandLine(toolchain, false).startIPCAwareProcess(environment.project, emulateTerminal = true)
|
||||
}
|
||||
|
||||
@Throws(ExecutionException::class)
|
||||
|
@ -65,9 +75,7 @@ abstract class ZigProfileState<T: ZigExecConfig<T>> (
|
|||
val workingDir = configuration.workingDirectory
|
||||
val zigExePath = toolchain.zig.path()
|
||||
|
||||
// TODO remove this check once JetBrains implements colored terminal in the debugger
|
||||
// https://youtrack.jetbrains.com/issue/CPP-11622/ANSI-color-codes-not-honored-in-Debug-Run-Configuration-output-window
|
||||
val cli = if (configuration.emulateTerminal() && !debug) PtyCommandLine().withConsoleMode(true).withParentEnvironmentType(GeneralCommandLine.ParentEnvironmentType.CONSOLE) else GeneralCommandLine()
|
||||
val cli = PtyCommandLine().withConsoleMode(false)
|
||||
cli.withExePath(zigExePath.pathString)
|
||||
workingDir.path?.let { cli.withWorkingDirectory(it) }
|
||||
cli.withCharset(Charsets.UTF_8)
|
||||
|
@ -75,22 +83,3 @@ abstract class ZigProfileState<T: ZigExecConfig<T>> (
|
|||
return configuration.patchCommandLine(cli)
|
||||
}
|
||||
}
|
||||
|
||||
@Throws(ExecutionException::class)
|
||||
suspend fun executeCommandLine(commandLine: GeneralCommandLine, environment: ExecutionEnvironment): DefaultExecutionResult {
|
||||
val handler = startProcess(commandLine, environment.project)
|
||||
val console = BuildTextConsoleView(environment.project, false, emptyList())
|
||||
console.attachToProcess(handler)
|
||||
return DefaultExecutionResult(console, handler)
|
||||
}
|
||||
|
||||
@Throws(ExecutionException::class)
|
||||
suspend fun startProcess(commandLine: GeneralCommandLine, project: Project): ProcessHandler {
|
||||
val ipc = IPCUtil.wrapWithIPC(commandLine)
|
||||
val handler = ZigProcessHandler(ipc?.cli ?: commandLine)
|
||||
ProcessTerminatedListener.attach(handler)
|
||||
if (ipc != null) {
|
||||
project.ipc?.launchWatcher(ipc, handler.process)
|
||||
}
|
||||
return handler
|
||||
}
|
||||
|
|
|
@ -25,7 +25,6 @@ package com.falsepattern.zigbrains.project.execution.build
|
|||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
||||
import com.falsepattern.zigbrains.project.execution.base.*
|
||||
import com.falsepattern.zigbrains.shared.ZBFeatures
|
||||
import com.falsepattern.zigbrains.shared.cli.coloredCliFlags
|
||||
import com.intellij.execution.ExecutionException
|
||||
import com.intellij.execution.Executor
|
||||
import com.intellij.execution.configurations.ConfigurationFactory
|
||||
|
@ -37,8 +36,6 @@ class ZigExecConfigBuild(project: Project, factory: ConfigurationFactory): ZigEx
|
|||
private set
|
||||
var extraArgs = ArgsConfigurable("compilerArgs", ZigBrainsBundle.message("exec.option.label.build.args"))
|
||||
private set
|
||||
var colored = ColoredConfigurable("colored")
|
||||
private set
|
||||
var debugBuildSteps = ArgsConfigurable("debugBuildSteps", ZigBrainsBundle.message("exec.option.label.build.steps-debug"))
|
||||
private set
|
||||
var debugExtraArgs = ArgsConfigurable("debugCompilerArgs", ZigBrainsBundle.message("exec.option.label.build.args-debug"))
|
||||
|
@ -54,7 +51,6 @@ class ZigExecConfigBuild(project: Project, factory: ConfigurationFactory): ZigEx
|
|||
result.add("build")
|
||||
val steps = if (debug) debugBuildSteps.argsSplit() else buildSteps.argsSplit()
|
||||
result.addAll(steps)
|
||||
result.addAll(coloredCliFlags(colored.value, debug))
|
||||
result.addAll(if (debug) debugExtraArgs.argsSplit() else extraArgs.argsSplit())
|
||||
return result
|
||||
}
|
||||
|
@ -66,14 +62,13 @@ class ZigExecConfigBuild(project: Project, factory: ConfigurationFactory): ZigEx
|
|||
val clone = super.clone()
|
||||
clone.buildSteps = buildSteps.clone()
|
||||
clone.exeArgs = exeArgs.clone()
|
||||
clone.colored = colored.clone()
|
||||
clone.exePath = exePath.clone()
|
||||
clone.exeArgs = exeArgs.clone()
|
||||
return clone
|
||||
}
|
||||
|
||||
override fun getConfigurables(): List<ZigConfigurable<*>> {
|
||||
val baseCfg = super.getConfigurables() + listOf(buildSteps, extraArgs, colored)
|
||||
val baseCfg = super.getConfigurables() + listOf(buildSteps, extraArgs)
|
||||
return if (ZBFeatures.debug()) {
|
||||
baseCfg + listOf(debugBuildSteps, debugExtraArgs, exePath, exeArgs)
|
||||
} else {
|
||||
|
|
|
@ -24,7 +24,6 @@ package com.falsepattern.zigbrains.project.execution.run
|
|||
|
||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
||||
import com.falsepattern.zigbrains.project.execution.base.*
|
||||
import com.falsepattern.zigbrains.shared.cli.coloredCliFlags
|
||||
import com.intellij.execution.ExecutionException
|
||||
import com.intellij.execution.Executor
|
||||
import com.intellij.execution.configurations.ConfigurationFactory
|
||||
|
@ -35,8 +34,6 @@ import kotlin.io.path.pathString
|
|||
class ZigExecConfigRun(project: Project, factory: ConfigurationFactory): ZigExecConfig<ZigExecConfigRun>(project, factory, ZigBrainsBundle.message("exec.type.run.label")) {
|
||||
var filePath = FilePathConfigurable("filePath", ZigBrainsBundle.message("exec.option.label.file-path"))
|
||||
private set
|
||||
var colored = ColoredConfigurable("colored")
|
||||
private set
|
||||
var optimization = OptimizationConfigurable("optimization")
|
||||
private set
|
||||
var compilerArgs = ArgsConfigurable("compilerArgs", ZigBrainsBundle.message("exec.option.label.compiler-args"))
|
||||
|
@ -47,7 +44,6 @@ class ZigExecConfigRun(project: Project, factory: ConfigurationFactory): ZigExec
|
|||
override suspend fun buildCommandLineArgs(debug: Boolean): List<String> {
|
||||
val result = ArrayList<String>()
|
||||
result.add(if (debug) "build-exe" else "run")
|
||||
result.addAll(coloredCliFlags(colored.value, debug))
|
||||
result.add(filePath.path?.pathString ?: throw ExecutionException(ZigBrainsBundle.message("exception.zig.empty-file-path")))
|
||||
if (!debug || optimization.forced) {
|
||||
result.addAll(listOf("-O", optimization.level.name))
|
||||
|
@ -66,7 +62,6 @@ class ZigExecConfigRun(project: Project, factory: ConfigurationFactory): ZigExec
|
|||
override fun clone(): ZigExecConfigRun {
|
||||
val clone = super.clone()
|
||||
clone.filePath = filePath.clone()
|
||||
clone.colored = colored.clone()
|
||||
clone.compilerArgs = compilerArgs.clone()
|
||||
clone.optimization = optimization.clone()
|
||||
clone.exeArgs = exeArgs.clone()
|
||||
|
@ -74,7 +69,7 @@ class ZigExecConfigRun(project: Project, factory: ConfigurationFactory): ZigExec
|
|||
}
|
||||
|
||||
override fun getConfigurables(): List<ZigConfigurable<*>> {
|
||||
return super.getConfigurables() + listOf(filePath, optimization, colored, compilerArgs, exeArgs)
|
||||
return super.getConfigurables() + listOf(filePath, optimization, compilerArgs, exeArgs)
|
||||
}
|
||||
|
||||
override fun getState(executor: Executor, environment: ExecutionEnvironment): ZigProfileState<ZigExecConfigRun> {
|
||||
|
|
|
@ -24,7 +24,6 @@ package com.falsepattern.zigbrains.project.execution.test
|
|||
|
||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
||||
import com.falsepattern.zigbrains.project.execution.base.*
|
||||
import com.falsepattern.zigbrains.shared.cli.coloredCliFlags
|
||||
import com.intellij.execution.ExecutionException
|
||||
import com.intellij.execution.Executor
|
||||
import com.intellij.execution.configurations.ConfigurationFactory
|
||||
|
@ -35,8 +34,6 @@ import kotlin.io.path.pathString
|
|||
class ZigExecConfigTest(project: Project, factory: ConfigurationFactory): ZigExecConfig<ZigExecConfigTest>(project, factory, ZigBrainsBundle.message("exec.type.test.label")) {
|
||||
var filePath = FilePathConfigurable("filePath", ZigBrainsBundle.message("exec.option.label.file-path"))
|
||||
private set
|
||||
var colored = ColoredConfigurable("colored")
|
||||
private set
|
||||
var optimization = OptimizationConfigurable("optimization")
|
||||
private set
|
||||
var compilerArgs = ArgsConfigurable("compilerArgs", ZigBrainsBundle.message("exec.option.label.compiler-args"))
|
||||
|
@ -46,7 +43,6 @@ class ZigExecConfigTest(project: Project, factory: ConfigurationFactory): ZigExe
|
|||
override suspend fun buildCommandLineArgs(debug: Boolean): List<String> {
|
||||
val result = ArrayList<String>()
|
||||
result.add("test")
|
||||
result.addAll(coloredCliFlags(colored.value, debug))
|
||||
result.add(filePath.path?.pathString ?: throw ExecutionException(ZigBrainsBundle.message("exception.zig.empty-file-path")))
|
||||
if (!debug || optimization.forced) {
|
||||
result.addAll(listOf("-O", optimization.level.name))
|
||||
|
@ -64,14 +60,13 @@ class ZigExecConfigTest(project: Project, factory: ConfigurationFactory): ZigExe
|
|||
override fun clone(): ZigExecConfigTest {
|
||||
val clone = super.clone()
|
||||
clone.filePath = filePath.clone()
|
||||
clone.colored = colored.clone()
|
||||
clone.compilerArgs = compilerArgs.clone()
|
||||
clone.optimization = optimization.clone()
|
||||
return clone
|
||||
}
|
||||
|
||||
override fun getConfigurables(): List<ZigConfigurable<*>> {
|
||||
return super.getConfigurables() + listOf(filePath, optimization, colored, compilerArgs)
|
||||
return super.getConfigurables() + listOf(filePath, optimization, compilerArgs)
|
||||
}
|
||||
|
||||
override fun getState(executor: Executor, environment: ExecutionEnvironment): ZigProfileState<ZigExecConfigTest> {
|
||||
|
|
|
@ -29,6 +29,7 @@ import com.intellij.ide.util.projectWizard.ModuleBuilder
|
|||
import com.intellij.ide.util.projectWizard.ModuleWizardStep
|
||||
import com.intellij.ide.util.projectWizard.WizardContext
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.module.ModuleType
|
||||
import com.intellij.openapi.roots.ModifiableRootModel
|
||||
import com.intellij.openapi.util.Disposer
|
||||
|
@ -58,7 +59,7 @@ class ZigModuleBuilder: ModuleBuilder() {
|
|||
val root = contentEntry.file ?: return
|
||||
val config = configurationData ?: return
|
||||
config.generateProject(this, rootModel.project, root, forceGitignore)
|
||||
withEDTContext {
|
||||
withEDTContext(ModalityState.defaultModalityState()) {
|
||||
root.refresh(false, true)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -119,10 +119,10 @@ data class ZigProjectConfigurationData(
|
|||
if (git) {
|
||||
project.zigCoroutineScope.launch {
|
||||
GitRepositoryInitializer.getInstance()?.initRepository(project, baseDir)
|
||||
createGitIgnoreFile(project, baseDir, requestor)
|
||||
createGitIgnoreFile(baseDir, requestor)
|
||||
}
|
||||
} else if (forceGitignore) {
|
||||
createGitIgnoreFile(project, baseDir, requestor)
|
||||
createGitIgnoreFile(baseDir, requestor)
|
||||
}
|
||||
|
||||
return@reportProgress true
|
||||
|
@ -131,7 +131,7 @@ data class ZigProjectConfigurationData(
|
|||
|
||||
}
|
||||
|
||||
private suspend fun createGitIgnoreFile(project: Project, projectDir: VirtualFile, requestor: Any) {
|
||||
private suspend fun createGitIgnoreFile(projectDir: VirtualFile, requestor: Any) {
|
||||
if (projectDir.findChild(".gitignore") != null) {
|
||||
return
|
||||
}
|
||||
|
|
|
@ -26,11 +26,12 @@ import com.intellij.execution.configurations.GeneralCommandLine
|
|||
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.openapi.util.Key
|
||||
import com.pty4j.PtyProcess
|
||||
import java.nio.charset.Charset
|
||||
|
||||
class ZigProcessHandler : KillableColoredProcessHandler, ColoredTextAcceptor {
|
||||
class ZigProcessHandler : KillableProcessHandler {
|
||||
constructor(commandLine: GeneralCommandLine) : super(commandLine) {
|
||||
setHasPty(commandLine is PtyCommandLine)
|
||||
setShouldDestroyProcessRecursively(!hasPty())
|
||||
|
@ -40,57 +41,4 @@ class ZigProcessHandler : KillableColoredProcessHandler, ColoredTextAcceptor {
|
|||
setHasPty(process is PtyProcess)
|
||||
setShouldDestroyProcessRecursively(!hasPty())
|
||||
}
|
||||
|
||||
override fun coloredTextAvailable(text: String, attributes: Key<*>) {
|
||||
super.coloredTextAvailable(text.translateVT100Escapes(), attributes)
|
||||
}
|
||||
}
|
||||
|
||||
private val VT100_CHARS = CharArray(256).apply {
|
||||
this.fill(' ')
|
||||
this[0x6A] = '┘'
|
||||
this[0x6B] = '┐'
|
||||
this[0x6C] = '┌'
|
||||
this[0x6D] = '└'
|
||||
this[0x6E] = '┼'
|
||||
this[0x71] = '─'
|
||||
this[0x74] = '├'
|
||||
this[0x75] = '┤'
|
||||
this[0x76] = '┴'
|
||||
this[0x77] = '┬'
|
||||
this[0x78] = '│'
|
||||
}
|
||||
|
||||
private const val VT100_BEGIN_SEQ = "\u001B(0"
|
||||
private const val VT100_END_SEQ = "\u001B(B"
|
||||
private const val VT100_BEGIN_SEQ_LENGTH: Int = VT100_BEGIN_SEQ.length
|
||||
private const val VT100_END_SEQ_LENGTH: Int = VT100_END_SEQ.length
|
||||
|
||||
private fun String.translateVT100Escapes(): String {
|
||||
var offset = 0
|
||||
val result = StringBuilder()
|
||||
val textLength = length
|
||||
while (offset < textLength) {
|
||||
val startIndex = indexOf(VT100_BEGIN_SEQ, offset)
|
||||
if (startIndex < 0) {
|
||||
result.append(substring(offset, textLength).replace(VT100_END_SEQ, ""))
|
||||
break
|
||||
}
|
||||
result.append(this, offset, startIndex)
|
||||
val blockOffset = startIndex + VT100_BEGIN_SEQ_LENGTH
|
||||
var endIndex = indexOf(VT100_END_SEQ, blockOffset)
|
||||
if (endIndex < 0) {
|
||||
endIndex = textLength
|
||||
}
|
||||
for (i in blockOffset until endIndex) {
|
||||
val c = this[i].code
|
||||
if (c >= 256) {
|
||||
result.append(c)
|
||||
} else {
|
||||
result.append(VT100_CHARS[c])
|
||||
}
|
||||
}
|
||||
offset = endIndex + VT100_END_SEQ_LENGTH
|
||||
}
|
||||
return result.toString()
|
||||
}
|
|
@ -24,7 +24,6 @@ package com.falsepattern.zigbrains.project.run
|
|||
|
||||
import com.falsepattern.zigbrains.project.execution.base.ZigExecConfig
|
||||
import com.falsepattern.zigbrains.project.execution.base.ZigProfileState
|
||||
import com.falsepattern.zigbrains.project.execution.base.executeCommandLine
|
||||
import com.falsepattern.zigbrains.project.toolchain.AbstractZigToolchain
|
||||
import com.falsepattern.zigbrains.shared.coroutine.withEDTContext
|
||||
import com.intellij.execution.configurations.RunProfile
|
||||
|
@ -36,8 +35,7 @@ import com.intellij.openapi.application.ModalityState
|
|||
|
||||
class ZigRegularRunner: ZigProgramRunner<ZigProfileState<*>>(DefaultRunExecutor.EXECUTOR_ID) {
|
||||
override suspend fun execute(state: ZigProfileState<*>, toolchain: AbstractZigToolchain, environment: ExecutionEnvironment): RunContentDescriptor? {
|
||||
val cli = state.getCommandLine(toolchain, false)
|
||||
val exec = executeCommandLine(cli, environment)
|
||||
val exec = state.execute(environment.executor, this)
|
||||
return withEDTContext(ModalityState.any()) {
|
||||
val runContentBuilder = RunContentBuilder(exec, environment)
|
||||
runContentBuilder.showRunContent(null)
|
||||
|
|
|
@ -97,7 +97,7 @@ class ZigProjectSettingsPanel(private val holder: ZigProjectConfigurationProvide
|
|||
}
|
||||
|
||||
private fun dispatchAutodetect(force: Boolean) {
|
||||
project.zigCoroutineScope.launchWithEDT {
|
||||
project.zigCoroutineScope.launchWithEDT(ModalityState.any()) {
|
||||
withModalProgress(ModalTaskOwner.component(pathToToolchain), "Detecting Zig...", TaskCancellation.cancellable()) {
|
||||
autodetect(force)
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ import com.falsepattern.zigbrains.project.steps.discovery.ZigStepDiscoveryListen
|
|||
import com.falsepattern.zigbrains.shared.coroutine.withEDTContext
|
||||
import com.falsepattern.zigbrains.shared.zigCoroutineScope
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.ModalityState
|
||||
import com.intellij.openapi.components.Service
|
||||
import com.intellij.openapi.components.service
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
|
@ -90,7 +91,7 @@ class ZigStepDiscoveryService(private val project: Project) {
|
|||
null
|
||||
}
|
||||
if (result == null) {
|
||||
{}
|
||||
|
||||
} else if (result.checkSuccess(LOG)) {
|
||||
currentTimeoutSec = DEFAULT_TIMEOUT_SEC
|
||||
val lines = result.stdoutLines
|
||||
|
@ -124,7 +125,7 @@ class ZigStepDiscoveryService(private val project: Project) {
|
|||
}
|
||||
|
||||
private suspend fun dispatchReload() {
|
||||
withEDTContext {
|
||||
withEDTContext(ModalityState.defaultModalityState()) {
|
||||
FileDocumentManager.getInstance().saveAllDocuments()
|
||||
}
|
||||
doReload()
|
||||
|
|
|
@ -81,18 +81,18 @@ class BuildToolWindowContext(private val project: Project): Disposable {
|
|||
val tree = Tree(model).also { it.isRootVisible = false }
|
||||
}
|
||||
private val viewPanel = JPanel(VerticalLayout(0))
|
||||
private val steps = TreeBox()
|
||||
private val build = if (IPCUtil.haveIPC) TreeBox() else null
|
||||
private val stepsBox = TreeBox()
|
||||
private val buildBox = if (IPCUtil.haveIPC) TreeBox() else null
|
||||
private var live = AtomicBoolean(true)
|
||||
init {
|
||||
viewPanel.add(JBLabel(ZigBrainsBundle.message("build.tool.window.tree.steps.label")))
|
||||
viewPanel.add(steps.panel)
|
||||
steps.panel.setNotScanned()
|
||||
viewPanel.add(stepsBox.panel)
|
||||
stepsBox.panel.setNotScanned()
|
||||
|
||||
steps.tree.addMouseListener(object : MouseAdapter() {
|
||||
stepsBox.tree.addMouseListener(object : MouseAdapter() {
|
||||
override fun mouseClicked(e: MouseEvent) {
|
||||
if (e.clickCount == 2) {
|
||||
val node = steps.tree.lastSelectedPathComponent as? DefaultMutableTreeNode ?: return
|
||||
val node = stepsBox.tree.lastSelectedPathComponent as? DefaultMutableTreeNode ?: return
|
||||
val step = node.userObject as? StepNodeDescriptor ?: return
|
||||
|
||||
val stepName = step.element?.name ?: return
|
||||
|
@ -112,10 +112,10 @@ class BuildToolWindowContext(private val project: Project): Disposable {
|
|||
}
|
||||
})
|
||||
|
||||
if (build != null) {
|
||||
if (buildBox != null) {
|
||||
viewPanel.add(JBLabel(ZigBrainsBundle.message("build.tool.window.tree.build.label")))
|
||||
viewPanel.add(build.panel)
|
||||
build.panel.setNoBuilds()
|
||||
viewPanel.add(buildBox.panel)
|
||||
buildBox.panel.setNoBuilds()
|
||||
|
||||
project.zigCoroutineScope.launch {
|
||||
while (!project.isDisposed && live.get()) {
|
||||
|
@ -126,14 +126,14 @@ class BuildToolWindowContext(private val project: Project): Disposable {
|
|||
ipc.mutex.withLock {
|
||||
withEDTContext(ModalityState.any()) {
|
||||
if (ipc.nodes.isEmpty()) {
|
||||
build.root.removeAllChildren()
|
||||
build.panel.setNoBuilds()
|
||||
buildBox.root.removeAllChildren()
|
||||
buildBox.panel.setNoBuilds()
|
||||
return@withEDTContext
|
||||
}
|
||||
val allNodes = ArrayList(ipc.nodes)
|
||||
val existingNodes = ArrayList<ZigIPCService.IPCTreeNode>()
|
||||
val removedNodes = ArrayList<ZigIPCService.IPCTreeNode>()
|
||||
build.root.children().iterator().forEach { child ->
|
||||
buildBox.root.children().iterator().forEach { child ->
|
||||
if (child !is ZigIPCService.IPCTreeNode) {
|
||||
return@forEach
|
||||
}
|
||||
|
@ -145,18 +145,18 @@ class BuildToolWindowContext(private val project: Project): Disposable {
|
|||
}
|
||||
val newNodes = ArrayList<MutableTreeNode>(allNodes)
|
||||
newNodes.removeAll(existingNodes)
|
||||
removedNodes.forEach { build.root.remove(it) }
|
||||
newNodes.forEach { build.root.add(it) }
|
||||
removedNodes.forEach { buildBox.root.remove(it) }
|
||||
newNodes.forEach { buildBox.root.add(it) }
|
||||
if (removedNodes.isNotEmpty() || newNodes.isNotEmpty()) {
|
||||
build.model.reload(build.root)
|
||||
buildBox.model.reload(buildBox.root)
|
||||
}
|
||||
if (build.root.childCount == 0) {
|
||||
build.panel.setNoBuilds()
|
||||
if (buildBox.root.childCount == 0) {
|
||||
buildBox.panel.setNoBuilds()
|
||||
} else {
|
||||
build.panel.setViewportBody(build.tree)
|
||||
buildBox.panel.setViewportBody(buildBox.tree)
|
||||
}
|
||||
for (bn in allNodes) {
|
||||
expandRecursively(build, bn)
|
||||
expandRecursively(buildBox, bn)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -220,28 +220,28 @@ class BuildToolWindowContext(private val project: Project): Disposable {
|
|||
|
||||
inner class BuildReloadListener: ZigStepDiscoveryListener {
|
||||
override suspend fun preReload() {
|
||||
steps.panel.setRunningZigBuild()
|
||||
stepsBox.panel.setRunningZigBuild()
|
||||
}
|
||||
|
||||
override suspend fun postReload(stepInfo: List<Pair<String, String?>>) {
|
||||
steps.root.removeAllChildren()
|
||||
for ((task, description) in stepInfo) {
|
||||
override suspend fun postReload(steps: List<Pair<String, String?>>) {
|
||||
stepsBox.root.removeAllChildren()
|
||||
for ((task, description) in steps) {
|
||||
val icon = when(task) {
|
||||
"install" -> AllIcons.Actions.Install
|
||||
"uninstall" -> AllIcons.Actions.Uninstall
|
||||
else -> AllIcons.RunConfigurations.TestState.Run
|
||||
}
|
||||
steps.root.add(DefaultMutableTreeNode(StepNodeDescriptor(project, task, icon, description)))
|
||||
stepsBox.root.add(DefaultMutableTreeNode(StepNodeDescriptor(project, task, icon, description)))
|
||||
}
|
||||
withEDTContext(ModalityState.any()) {
|
||||
steps.model.reload(steps.root)
|
||||
steps.panel.setViewportBody(steps.tree)
|
||||
stepsBox.model.reload(stepsBox.root)
|
||||
stepsBox.panel.setViewportBody(stepsBox.tree)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun errorReload(type: ZigStepDiscoveryListener.ErrorType, details: String?) {
|
||||
withEDTContext(ModalityState.any()) {
|
||||
steps.panel.setViewportError(ZigBrainsBundle.message(when(type) {
|
||||
stepsBox.panel.setViewportError(ZigBrainsBundle.message(when(type) {
|
||||
ZigStepDiscoveryListener.ErrorType.MissingToolchain -> "build.tool.window.status.error.missing-toolchain"
|
||||
ZigStepDiscoveryListener.ErrorType.MissingZigExe -> "build.tool.window.status.error.missing-zig-exe"
|
||||
ZigStepDiscoveryListener.ErrorType.MissingBuildZig -> "build.tool.window.status.error.missing-build-zig"
|
||||
|
@ -252,7 +252,7 @@ class BuildToolWindowContext(private val project: Project): Disposable {
|
|||
|
||||
override suspend fun timeoutReload(seconds: Int) {
|
||||
withEDTContext(ModalityState.any()) {
|
||||
steps.panel.setViewportError(ZigBrainsBundle.message("build.tool.window.status.timeout", seconds), null)
|
||||
stepsBox.panel.setViewportError(ZigBrainsBundle.message("build.tool.window.status.timeout", seconds), null)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,13 +23,18 @@
|
|||
package com.falsepattern.zigbrains.shared.cli
|
||||
|
||||
import com.falsepattern.zigbrains.ZigBrainsBundle
|
||||
import com.falsepattern.zigbrains.project.run.ZigProcessHandler
|
||||
import com.falsepattern.zigbrains.shared.ipc.IPCUtil
|
||||
import com.falsepattern.zigbrains.shared.ipc.ipc
|
||||
import com.intellij.execution.ExecutionException
|
||||
import com.intellij.execution.configurations.GeneralCommandLine
|
||||
import com.intellij.execution.process.ProcessHandler
|
||||
import com.intellij.execution.process.ProcessOutput
|
||||
import com.intellij.execution.process.ProcessTerminatedListener
|
||||
import com.intellij.openapi.options.ConfigurationException
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.util.io.awaitExit
|
||||
import com.intellij.util.system.OS
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runInterruptible
|
||||
import kotlinx.coroutines.withContext
|
||||
|
@ -108,14 +113,6 @@ fun translateCommandline(toProcess: String): List<String> {
|
|||
return result
|
||||
}
|
||||
|
||||
fun coloredCliFlags(colored: Boolean, debug: Boolean): List<String> {
|
||||
return if (debug) {
|
||||
emptyList()
|
||||
} else {
|
||||
listOf("--color", if (colored) "on" else "off")
|
||||
}
|
||||
}
|
||||
|
||||
fun createCommandLineSafe(
|
||||
workingDirectory: Path?,
|
||||
exe: Path,
|
||||
|
@ -133,14 +130,27 @@ fun createCommandLineSafe(
|
|||
return Result.success(cli)
|
||||
}
|
||||
|
||||
suspend fun GeneralCommandLine.call(timeoutMillis: Long = Long.MAX_VALUE, ipcProject: Project? = null): Result<ProcessOutput> {
|
||||
val ipc = if (ipcProject != null) IPCUtil.wrapWithIPC(this) else null
|
||||
@Throws(ExecutionException::class)
|
||||
suspend fun GeneralCommandLine.startIPCAwareProcess(project: Project?, emulateTerminal: Boolean = false): ZigProcessHandler {
|
||||
val ipc = if (project != null && !emulateTerminal) IPCUtil.wrapWithIPC(this) else null
|
||||
val cli = ipc?.cli ?: this
|
||||
if (emulateTerminal && OS.CURRENT != OS.Windows && !cli.environment.contains("TERM")) {
|
||||
cli.withEnvironment("TERM", "xterm-256color")
|
||||
}
|
||||
val handler = ZigProcessHandler(cli)
|
||||
ProcessTerminatedListener.attach(handler)
|
||||
|
||||
if (ipc != null) {
|
||||
project!!.ipc?.launchWatcher(ipc, handler.process)
|
||||
}
|
||||
return handler
|
||||
}
|
||||
|
||||
|
||||
suspend fun GeneralCommandLine.call(timeoutMillis: Long = Long.MAX_VALUE, ipcProject: Project? = null): Result<ProcessOutput> {
|
||||
val (process, exitCode) = withContext(Dispatchers.IO) {
|
||||
val process = cli.createProcess()
|
||||
if (ipc != null) {
|
||||
ipcProject!!.ipc?.launchWatcher(ipc, process)
|
||||
}
|
||||
val handler = startIPCAwareProcess(ipcProject)
|
||||
val process = handler.process
|
||||
val exit = withTimeoutOrNull(timeoutMillis) {
|
||||
process.awaitExit()
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ inline fun <T> runModalOrBlocking(taskOwnerFactory: () -> ModalTaskOwner, titleF
|
|||
}
|
||||
}
|
||||
|
||||
suspend inline fun <T> withEDTContext(state: ModalityState = ModalityState.defaultModalityState(), noinline block: suspend CoroutineScope.() -> T): T {
|
||||
suspend inline fun <T> withEDTContext(state: ModalityState, noinline block: suspend CoroutineScope.() -> T): T {
|
||||
return withContext(Dispatchers.EDT + state.asContextElement(), block = block)
|
||||
}
|
||||
|
||||
|
@ -49,10 +49,10 @@ suspend inline fun <T> withCurrentEDTModalityContext(noinline block: suspend Cor
|
|||
}
|
||||
}
|
||||
|
||||
suspend inline fun <T> runInterruptibleEDT(state: ModalityState = ModalityState.defaultModalityState(), noinline targetAction: () -> T): T {
|
||||
suspend inline fun <T> runInterruptibleEDT(state: ModalityState, noinline targetAction: () -> T): T {
|
||||
return runInterruptible(Dispatchers.EDT + state.asContextElement(), block = targetAction)
|
||||
}
|
||||
|
||||
fun CoroutineScope.launchWithEDT(state: ModalityState = ModalityState.defaultModalityState(), block: suspend CoroutineScope.() -> Unit): Job {
|
||||
fun CoroutineScope.launchWithEDT(state: ModalityState, block: suspend CoroutineScope.() -> Unit): Job {
|
||||
return launch(Dispatchers.EDT + state.asContextElement(), block = block)
|
||||
}
|
|
@ -74,7 +74,7 @@ object IPCUtil {
|
|||
val cli = GeneralCommandLine(it)
|
||||
val tmpFile = FileUtil.createTempFile("zigbrains-bash-detection", null, true).toPath()
|
||||
try {
|
||||
cli.addParameters("-c", "exec {var}>${tmpFile.pathString}; echo foo >&\$var; exec {var}>&-")
|
||||
cli.addParameters("-c", "exec {var}>${tmpFile.pathString}; echo foo >&\$var; ZB_EXIT=\$?; exec {var}>&-; exit \$ZB_EXIT")
|
||||
val process = cli.createProcess()
|
||||
val exitCode = process.awaitExit()
|
||||
if (exitCode != 0) {
|
||||
|
@ -100,7 +100,7 @@ object IPCUtil {
|
|||
val (fifoFile, fifo) = info!!.mkfifo.createTemp() ?: return null
|
||||
//FIFO created, hack cli
|
||||
val exePath = cli.exePath
|
||||
val args = "exec {var}>${fifoFile.pathString}; ZIG_PROGRESS=\$var $exePath ${cli.parametersList.parametersString}; exec {var}>&-"
|
||||
val args = "exec {var}>${fifoFile.pathString}; ZIG_PROGRESS=\$var $exePath ${cli.parametersList.parametersString}; ZB_EXIT=\$?; exec {var}>&-; exit \$ZB_EXIT"
|
||||
cli.withExePath(info!!.bash)
|
||||
cli.parametersList.clearAll()
|
||||
cli.addParameters("-c", args)
|
||||
|
|
|
@ -55,18 +55,16 @@ class ZonBlock(
|
|||
|
||||
override fun getChildIndent(): Indent {
|
||||
val node = this.node
|
||||
return getIndentBasedOnParentType(node, null, node.elementType, PLACEHOLDER)
|
||||
return getIndentBasedOnParentType(node.elementType, PLACEHOLDER)
|
||||
}
|
||||
|
||||
override fun getIndent(): Indent {
|
||||
val node = this.node
|
||||
val parent = node.treeParent ?: return noneIndent
|
||||
return getIndentBasedOnParentType(parent, node, parent.elementType, node.elementType)
|
||||
return getIndentBasedOnParentType(parent.elementType, node.elementType)
|
||||
}
|
||||
}
|
||||
private fun getIndentBasedOnParentType(
|
||||
parent: ASTNode,
|
||||
child: ASTNode?,
|
||||
parentType: IElementType,
|
||||
childType: IElementType
|
||||
): Indent {
|
||||
|
|
|
@ -65,11 +65,9 @@ exec.type.run.label=Zig Run
|
|||
exec.type.test.label=Zig Test
|
||||
exec.type.build.label=Zig Build
|
||||
exec.option.label.working-directory=&Working directory:
|
||||
exec.option.label.colored-terminal=Colored terminal
|
||||
exec.option.label.direnv=Use direnv
|
||||
exec.option.label.optimization=Optimization level
|
||||
exec.option.label.optimization.force=Force even in debug runs
|
||||
exec.option.label.emulate-terminal=Emulate terminal
|
||||
exec.option.label.file-path=File Path
|
||||
exec.option.label.compiler-args=Extra compiler command line arguments
|
||||
exec.option.label.exe-args=Output program command line arguments
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
pluginName=ZigBrains
|
||||
pluginRepositoryUrl=https://github.com/FalsePattern/ZigBrains
|
||||
|
||||
pluginVersion=23.1.2
|
||||
pluginVersion=24.0.0
|
||||
|
||||
pluginSinceBuild=242
|
||||
pluginUntilBuild=242.*
|
||||
|
|
|
@ -279,7 +279,7 @@ class ZLSSettingsPanel(private val project: Project) : ZigProjectConfigurationPr
|
|||
}
|
||||
|
||||
private fun dispatchAutodetect(force: Boolean) {
|
||||
project.zigCoroutineScope.launchWithEDT {
|
||||
project.zigCoroutineScope.launchWithEDT(ModalityState.any()) {
|
||||
withModalProgress(ModalTaskOwner.component(zlsPath), "Detecting ZLS...", TaskCancellation.cancellable()) {
|
||||
autodetect(force)
|
||||
}
|
||||
|
|
|
@ -6,7 +6,6 @@ settings.zls-version.label=Detected ZLS version
|
|||
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.browse.title=Path to the Custom ZLS Config File (Optional)
|
||||
settings.zls-path.use-direnv.label=Use direnv
|
||||
settings.inlay-hints-group.label=Inlay Hints
|
||||
settings.inlay-hints-enable.label=Enable
|
||||
settings.inlay-hints-enable.tooltip=Toggle this to enable/disable all inlay hints
|
||||
|
@ -50,7 +49,6 @@ settings.build_runner_path.label=Build runner path
|
|||
settings.build_runner_path.tooltip=Specify a custom build runner to resolve build system information.
|
||||
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`.
|
||||
configurable.name.zls.settings=ZLS Settings
|
||||
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}
|
||||
|
|
Loading…
Add table
Reference in a new issue