Skip to content

Commit

Permalink
Allow installing all dependency groups using line markers
Browse files Browse the repository at this point in the history
  • Loading branch information
InSyncWithFoo committed Nov 21, 2024
1 parent 906c6d9 commit e5df199
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 13 deletions.
Binary file modified docs/assets/features-dependency-groups-line-markers.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions docs/other-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,11 @@ along with that group's declaration and vice versa.

Dependency groups can be installed
using their corresponding icons in the gutter.
The icon corresponding to the `[dependency-groups]`
table header installs all groups.

This is equivalent to running `uv sync --group ...` at the project's path
with the group name as argument.
This is equivalent to running `uv sync --group ...`/`uv sync --all-groups`
at the project's path.

![](./assets/features-dependency-groups-line-markers.png)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,23 @@ import com.intellij.execution.lineMarker.RunLineMarkerContributor
import com.intellij.openapi.project.DumbAware
import com.intellij.psi.PsiElement
import com.jetbrains.python.icons.PythonIcons
import insyncwithfoo.ryecharm.keyValuePair
import insyncwithfoo.ryecharm.message
import org.toml.lang.psi.TomlKey
import org.toml.lang.psi.TomlKeySegment
import org.toml.lang.psi.TomlTable
import org.toml.lang.psi.ext.name
import org.toml.lang.psi.TomlElementTypes.BARE_KEY
import org.toml.lang.psi.TomlTableHeader


/**
* Show a line marker for each dependency group.
* Such markers can be clicked on to install the corresponding group.
* Show a line marker for each dependency group
* as well as the `[dependency-groups]` table header.
* Such markers can be clicked on to install
* either the corresponding group or all groups.
*
* ```toml
* 1 | [dependency-groups]
* 1 @ | [dependency-groups]
* 2 @ | foo = [
* 3 | "ruff"
* 4 | ]
Expand All @@ -37,18 +39,34 @@ internal class DependencyGroupInstaller : RunLineMarkerContributor(), DumbAware
override fun getInfo(element: PsiElement): Info? {
val segment = element.parent as? TomlKeySegment ?: return null
val key = segment.parent as? TomlKey ?: return null
val table = key.keyValuePair?.parent as? TomlTable ?: return null

val tableHeaderOrKeyValuePair = key.parent
val table = tableHeaderOrKeyValuePair.parent as? TomlTable ?: return null

if (!table.isDependencyGroupsTable) {
return null
}

return when (key.parent is TomlTableHeader) {
true -> getInfoForTableHeader(key)
else -> getInfoForNormalKey(key)
}
}

private fun getInfoForTableHeader(key: TomlKey): Info {
val icon = PythonIcons.Python.PythonPackages
val action = InstallDependencyGroup.all(key.project)

return Info(icon, arrayOf(action)) { message("lineMarkers.installDependencyGroups.all.tooltip") }
}

private fun getInfoForNormalKey(key: TomlKey): Info? {
val groupName = key.name ?: return null

val icon = PythonIcons.Python.PythonPackages
val action = InstallDependencyGroup(element.project, groupName)
val action = InstallDependencyGroup.group(key.project, groupName)

return Info(icon, arrayOf(action)) { message("lineMarkers.installDependencyGroup.tooltip", groupName) }
return Info(icon, arrayOf(action)) { message("lineMarkers.installDependencyGroups.single.tooltip", groupName) }
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.components.Service
import com.intellij.openapi.project.Project
import insyncwithfoo.ryecharm.Command
import insyncwithfoo.ryecharm.CoroutineService
import insyncwithfoo.ryecharm.launch
import insyncwithfoo.ryecharm.message
Expand All @@ -16,12 +17,21 @@ import insyncwithfoo.ryecharm.uv.commands.uv
import kotlinx.coroutines.CoroutineScope


private sealed class InstallKind {
data object All : InstallKind()
class Group(val name: String) : InstallKind()
}


/**
* Install a dependency group using `uv sync --group <group>`.
*
* @see DependencyGroupInstaller
*/
internal class InstallDependencyGroup(private val project: Project, private val group: String) : AnAction() {
internal class InstallDependencyGroup private constructor(
private val project: Project,
private val kind: InstallKind
) : AnAction() {

override fun actionPerformed(event: AnActionEvent) {
val uv = project.uv ?: return project.unableToRunCommand()
Expand All @@ -30,15 +40,28 @@ internal class InstallDependencyGroup(private val project: Project, private val
}

private fun Project.runUVSyncAndReport(uv: UV) = launch<Coroutine> {
val command = uv.sync(group)
val command = getCommand(uv)
val output = runInBackground(command)

notifyIfProcessIsUnsuccessfulOr(command, output) {
processCompletedSuccessfully(message("notifications.environmentSynchronized.body"))
}
}

private fun getCommand(uv: UV) = when (kind) {
is InstallKind.All -> uv.sync(allGroups = true)
is InstallKind.Group -> uv.sync(group = kind.name)
}

@Service(Service.Level.PROJECT)
private class Coroutine(override val scope: CoroutineScope) : CoroutineService

companion object {
fun all(project: Project) =
InstallDependencyGroup(project, InstallKind.All)

fun group(project: Project, name: String) =
InstallDependencyGroup(project, InstallKind.Group(name))
}

}
10 changes: 9 additions & 1 deletion src/main/kotlin/insyncwithfoo/ryecharm/uv/commands/UV.kt
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,21 @@ internal class UV private constructor(
fun remove(target: String) =
RemoveCommand().build(CommandArguments(target))

fun sync(group: String? = null): Command {
fun sync(group: String? = null, allGroups: Boolean = false): Command {
val arguments = CommandArguments()

if (group != null && allGroups) {
throw IllegalArgumentException("--group cannot be used with --all-groups")
}

if (group != null) {
arguments["--group"] = group
}

if (allGroups) {
arguments += "--all-groups"
}

return SyncCommand().build(arguments)
}

Expand Down
3 changes: 2 additions & 1 deletion src/main/resources/messages/ryecharm.properties
Original file line number Diff line number Diff line change
Expand Up @@ -450,7 +450,8 @@ documentation.popup.exampleUsage = Example:

############################################################ region # Line markers

lineMarkers.installDependencyGroup.tooltip = Install dependency group "{0}"
lineMarkers.installDependencyGroups.all.tooltip = Install all dependency groups
lineMarkers.installDependencyGroups.single.tooltip = Install dependency group "{0}"

############################################################ endregion

Expand Down
5 changes: 5 additions & 0 deletions src/test/kotlin/insyncwithfoo/ryecharm/uv/commands/UVTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,9 @@ internal class UVTest : CommandFactoryTest() {
assertEquals(projectPath, command.workingDirectory)
}

@Test(expected = IllegalArgumentException::class)
fun `test sync - groups`() {
uv.sync(group = "foo", allGroups = true)
}

}

0 comments on commit e5df199

Please sign in to comment.