Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,23 @@ import com.intellij.ui.SimpleTextAttributes

import com.jetbrains.python.icons.PythonIcons.Python.Virtualenv

import com.github.pyvenvmanage.settings.PyVenvManageSettings

class VenvProjectViewNodeDecorator : ProjectViewNodeDecorator {
override fun decorate(
node: ProjectViewNode<*>,
data: PresentationData,
) {
VenvUtils.getPyVenvCfg(node.virtualFile)?.let { pyVenvCfgPath ->
val pythonVersion = VenvVersionCache.getInstance().getVersion(pyVenvCfgPath.toString())
pythonVersion?.let { version ->
data.presentableText?.let { fileName ->
data.clearText()
data.addText(fileName, SimpleTextAttributes.REGULAR_ATTRIBUTES)
data.addText(" [$version]", SimpleTextAttributes.GRAY_ATTRIBUTES)
val settings = PyVenvManageSettings.getInstance()
if (settings.showVersionInProjectView) {
val pythonVersion = VenvVersionCache.getInstance().getVersion(pyVenvCfgPath.toString())
pythonVersion?.let { version ->
data.presentableText?.let { fileName ->
data.clearText()
data.addText(fileName, SimpleTextAttributes.REGULAR_ATTRIBUTES)
data.addText(settings.formatVersion(version), SimpleTextAttributes.GRAY_ATTRIBUTES)
}
}
}
data.setIcon(Virtualenv)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.github.pyvenvmanage.settings

import javax.swing.JCheckBox
import javax.swing.JComponent
import javax.swing.JPanel
import javax.swing.JTextField

import com.intellij.openapi.options.Configurable
import com.intellij.ui.components.JBLabel
import com.intellij.util.ui.FormBuilder

class PyVenvManageConfigurable : Configurable {
private var showVersionCheckBox: JCheckBox? = null
private var versionFormatField: JTextField? = null

override fun getDisplayName(): String = "PyVenv Manage"

override fun createComponent(): JComponent {
showVersionCheckBox = JCheckBox("Show Python version in project view")
versionFormatField =
JTextField().apply {
toolTipText = "Use \$version as placeholder for the version number"
}

return FormBuilder
.createFormBuilder()
.addComponent(showVersionCheckBox!!)
.addLabeledComponent(JBLabel("Version format:"), versionFormatField!!)
.addComponentFillVertically(JPanel(), 0)
.panel
}

override fun isModified(): Boolean {
val settings = PyVenvManageSettings.getInstance()
return showVersionCheckBox?.isSelected != settings.showVersionInProjectView ||
versionFormatField?.text != settings.versionFormat
}

override fun apply() {
val settings = PyVenvManageSettings.getInstance()
showVersionCheckBox?.isSelected?.let { settings.showVersionInProjectView = it }
versionFormatField?.text?.let { settings.versionFormat = it }
}

override fun reset() {
val settings = PyVenvManageSettings.getInstance()
showVersionCheckBox?.isSelected = settings.showVersionInProjectView
versionFormatField?.text = settings.versionFormat
}

override fun disposeUIResources() {
showVersionCheckBox = null
versionFormatField = null
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package com.github.pyvenvmanage.settings

import com.intellij.openapi.components.PersistentStateComponent
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)
@State(
name = "PyVenvManageSettings",
storages = [Storage("PyVenvManageSettings.xml")],
)
class PyVenvManageSettings : PersistentStateComponent<PyVenvManageSettings.State> {
private var state = State()

data class State(
var showVersionInProjectView: Boolean = true,
var versionFormat: String = " [\$version]",
)

override fun getState(): State = state

override fun loadState(state: State) {
this.state = state
}

var showVersionInProjectView: Boolean
get() = state.showVersionInProjectView
set(value) {
state.showVersionInProjectView = value
}

var versionFormat: String
get() = state.versionFormat
set(value) {
state.versionFormat = value
}

fun formatVersion(version: String): String = versionFormat.replace("\$version", version)

companion object {
fun getInstance(): PyVenvManageSettings = service()
}
}
5 changes: 5 additions & 0 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
<notificationGroup id="Python SDK change"
displayType="BALLOON"/>
<projectViewNodeDecorator implementation="com.github.pyvenvmanage.VenvProjectViewNodeDecorator"/>
<applicationConfigurable
parentId="tools"
instance="com.github.pyvenvmanage.settings.PyVenvManageConfigurable"
id="com.github.pyvenvmanage.settings.PyVenvManageConfigurable"
displayName="PyVenv Manage"/>
</extensions>

<actions>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ import com.intellij.ide.projectView.ProjectViewNode
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.ui.SimpleTextAttributes

import com.github.pyvenvmanage.settings.PyVenvManageSettings

class VenvProjectViewNodeDecoratorTest {
private lateinit var decorator: VenvProjectViewNodeDecorator
private lateinit var node: ProjectViewNode<*>
Expand All @@ -38,19 +40,26 @@ class VenvProjectViewNodeDecoratorTest {
@Nested
inner class DecorateTest {
private lateinit var versionCache: VenvVersionCache
private lateinit var settings: PyVenvManageSettings

@BeforeEach
fun setUpMocks() {
mockkObject(VenvUtils)
versionCache = mockk(relaxed = true)
mockkObject(VenvVersionCache.Companion)
every { VenvVersionCache.getInstance() } returns versionCache
settings = mockk(relaxed = true)
mockkObject(PyVenvManageSettings.Companion)
every { PyVenvManageSettings.getInstance() } returns settings
every { settings.showVersionInProjectView } returns true
every { settings.formatVersion(any()) } answers { " [${firstArg<String>()}]" }
}

@AfterEach
fun tearDown() {
unmockkObject(VenvUtils)
unmockkObject(VenvVersionCache.Companion)
unmockkObject(PyVenvManageSettings.Companion)
}

@Test
Expand Down Expand Up @@ -143,5 +152,23 @@ class VenvProjectViewNodeDecoratorTest {
// Version cache should be called twice (caching is handled by the cache service)
verify(exactly = 2) { versionCache.getVersion(pyvenvCfgPath.toString()) }
}

@Test
fun `respects showVersionInProjectView setting`(
@TempDir tempDir: Path,
) {
val pyvenvCfgPath = tempDir.resolve("pyvenv.cfg")
Files.writeString(pyvenvCfgPath, "version = 3.11.0")

every { settings.showVersionInProjectView } returns false
every { VenvUtils.getPyVenvCfg(virtualFile) } returns pyvenvCfgPath
every { data.presentableText } returns "venv"

decorator.decorate(node, data)

verify(exactly = 0) { data.clearText() }
verify(exactly = 0) { data.addText(any(), any<SimpleTextAttributes>()) }
verify { data.setIcon(any()) } // Icon is still set
}
}
}