Skip to content

Commit

Permalink
Adds a configuration option to enable a reload of the .envrc every ti…
Browse files Browse the repository at this point in the history
…me a run configuration is executed.

This is particularly useful when working with multiple projects in separate windows that have different .envrc files.
  • Loading branch information
sh41 committed Jan 25, 2024
1 parent d135d92 commit 0d035aa
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

## [Unreleased]
- Version range now includes 2023.3
- Adds a configuration option to enable a reload of the .envrc every time a run configuration is executed.

## [0.2.8] - 2023-08-15
- Version range now includes 2023.2
Expand Down
11 changes: 9 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,17 @@
<!-- Plugin description -->
This plugin provides an action to import environment variables from [direnv](https://github.com/direnv/direnv) into the Java process that is running the IDE.

To automatically load the `.envrc` file in the root of a project when you open it, visit <kbd>Settings</kbd> > <kbd>Tools</kbd> > <kbd>Direnv Settings</kbd> and tick the relevant checkbox.
### Automatic Import before every Run/Debug
To automatically load the environment variables from a `<project_root>/.envrc` file before each and every execution of a Run/Debug configuration, visit <kbd>Settings</kbd> > <kbd>Tools</kbd> > <kbd>Direnv Settings</kbd> and tick the relevant checkbox.

If you don't choose the automatic loading option, a popup notification will appear whenever a project with a `.envrc` file in the root is opened. You can load the `.envrc` file by clicking on the link in the notification.
On starting a Run/Debug job, a notification will show if the existing environment has been changed. The newly spawned process which executes the Run/Debug configuration will inherit the environment. If you often work with multiple project windows open in a single IDE instance, this is probably the best option for you.

### Automatic Import on Startup
To automatically load the environment variables from a `<project_root>/.envrc` file when you open the project, visit <kbd>Settings</kbd> > <kbd>Tools</kbd> > <kbd>Direnv Settings</kbd> and tick the relevant checkbox.

If "Automatic Import on Startup" is disabled, a popup notification will appear whenever a project with a `.envrc` file in the root is opened. You can load the `.envrc` file by clicking on the link in the notification.

### Manual Import
To manually load an `.envrc` file:
- If you have the main toolbar enabled (<kbd>View</kbd> > <kbd>Appearance</kbd> > <kbd>Main Toolbar</kbd>), a button next to the <kbd>Reload All from Disk</kbd> action will start the process.

Expand Down
4 changes: 2 additions & 2 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ plugins {
// Java support
id("java")
// Kotlin support
id("org.jetbrains.kotlin.jvm") version "1.7.21"
id("org.jetbrains.kotlin.jvm") version "1.7.22"
// Gradle IntelliJ Plugin
id("org.jetbrains.intellij") version "1.15.0"
id("org.jetbrains.intellij") version "1.17.0"
// Gradle Changelog Plugin
id("org.jetbrains.changelog") version "2.0.0"
// Gradle Qodana Plugin
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package systems.fehn.intellijdirenv;

import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import systems.fehn.intellijdirenv.services.DirenvProjectService;
import systems.fehn.intellijdirenv.settings.DirenvSettingsState;


class DirenvExecutionListener implements com.intellij.execution.ExecutionListener {
public DirenvExecutionListener() {
}

@Override
public void processStarting(@NotNull String executorId, @NotNull ExecutionEnvironment env) {
if ( !DirenvSettingsState.getInstance().direnvSettingsImportEveryExecution ) {
com.intellij.execution.ExecutionListener.super.processStarting(executorId, env);
return;
}

Project project = env.getProject();
DirenvProjectService service = project.getService(DirenvProjectService.class);
VirtualFile envrcFile = service.getProjectEnvrcFile();
if (envrcFile != null) {
service.importDirenv(envrcFile, false);
}
com.intellij.execution.ExecutionListener.super.processStarting(executorId, env);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public class DirenvSettingsComponent {
private final JPanel mainPanel;
private final TextFieldWithBrowseButton direnvPath = new TextFieldWithBrowseButton();
private final JBCheckBox direnvImportOnStartup = new JBCheckBox("Automatically import any .envrc in the project root when the project is opened.");
private final JBCheckBox direnvImportEveryExecution = new JBCheckBox("Automatically import any .envrc in the project root before every run/debug");


public DirenvSettingsComponent() {
Expand All @@ -21,6 +22,7 @@ public DirenvSettingsComponent() {
.createFormBuilder()
.addLabeledComponent(new JLabel("DirenvPath: "), direnvPath, 1, false)
.addComponent(direnvImportOnStartup, 1)
.addComponent(direnvImportEveryExecution, 1)
.addComponentFillVertically(new JPanel(), 0)
.getPanel();
}
Expand Down Expand Up @@ -49,4 +51,12 @@ public boolean getDirenvImportOnStartup() {
public void setDirenvImportOnStartup(boolean newStatus) {
direnvImportOnStartup.setSelected(newStatus);
}

public boolean getDirenvImportEveryExecution() {
return direnvImportEveryExecution.isSelected();
}

public void setDirenvImportEveryExecution(boolean newStatus) {
direnvImportEveryExecution.setSelected(newStatus);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,25 @@ public JComponent getPreferredFocusedComponent() {
@Override
public boolean isModified() {
DirenvSettingsState settings = DirenvSettingsState.getInstance();
return !direnvSettingsComponent.getDirenvPath().equals(settings.direnvSettingsPath) || direnvSettingsComponent.getDirenvImportOnStartup() != settings.direnvSettingsImportOnStartup;
return !direnvSettingsComponent.getDirenvPath().equals(settings.direnvSettingsPath) ||
direnvSettingsComponent.getDirenvImportOnStartup() != settings.direnvSettingsImportOnStartup ||
direnvSettingsComponent.getDirenvImportEveryExecution() != settings.direnvSettingsImportEveryExecution;
}

@Override
public void apply() {
DirenvSettingsState settings = DirenvSettingsState.getInstance();
settings.direnvSettingsPath = direnvSettingsComponent.getDirenvPath();
settings.direnvSettingsImportOnStartup = direnvSettingsComponent.getDirenvImportOnStartup();
settings.direnvSettingsImportEveryExecution = direnvSettingsComponent.getDirenvImportEveryExecution();
}

@Override
public void reset() {
DirenvSettingsState settings = DirenvSettingsState.getInstance();
direnvSettingsComponent.setDirenvPath(settings.direnvSettingsPath);
direnvSettingsComponent.setDirenvImportOnStartup(settings.direnvSettingsImportOnStartup);
direnvSettingsComponent.setDirenvImportEveryExecution(settings.direnvSettingsImportEveryExecution);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
public class DirenvSettingsState implements PersistentStateComponent<DirenvSettingsState> {
public String direnvSettingsPath = "";
public Boolean direnvSettingsImportOnStartup = false;
public Boolean direnvSettingsImportEveryExecution = false;

public static DirenvSettingsState getInstance() {
return ApplicationManager.getApplication().getService(DirenvSettingsState.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.intellij.execution.configurations.GeneralCommandLine
import com.intellij.notification.NotificationAction
import com.intellij.notification.NotificationType
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.Service
import com.intellij.openapi.diagnostic.logger
import com.intellij.openapi.diagnostic.trace
import com.intellij.openapi.fileEditor.FileEditorManager
Expand All @@ -18,6 +19,7 @@ import systems.fehn.intellijdirenv.notificationGroup
import systems.fehn.intellijdirenv.settings.DirenvSettingsState
import systems.fehn.intellijdirenv.switchNull

@Service(Service.Level.PROJECT)
class DirenvProjectService(private val project: Project) {
private val logger by lazy { logger<DirenvProjectService>() }

Expand All @@ -37,15 +39,15 @@ class DirenvProjectService(private val project: Project) {

private val jsonFactory by lazy { JsonFactory() }

fun importDirenv(envrcFile: VirtualFile) {
fun importDirenv(envrcFile: VirtualFile, notifyNoChange: Boolean = true) {
val process = executeDirenv(envrcFile, "export", "json")

if (process.waitFor() != 0) {
handleDirenvError(process, envrcFile)
return
}

val notification = jsonFactory.createParser(process.inputStream).use { parser ->
jsonFactory.createParser(process.inputStream).use { parser ->

try {
val didWork = handleDirenvOutput(parser)
Expand All @@ -56,26 +58,24 @@ class DirenvProjectService(private val project: Project) {
MyBundle.message("executedSuccessfully"),
"",
NotificationType.INFORMATION,
)
} else {
).notify(project)
} else if (notifyNoChange) {
notificationGroup
.createNotification(
MyBundle.message("alreadyUpToDate"),
"",
NotificationType.INFORMATION,
)
).notify(project)
}
} catch (e: EnvironmentService.ManipulateEnvironmentException) {
notificationGroup
.createNotification(
MyBundle.message("exceptionNotification"),
e.localizedMessage,
NotificationType.ERROR,
)
).notify(project)
}
}

notification.notify(project)
}

private fun handleDirenvOutput(parser: JsonParser): Boolean {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package systems.fehn.intellijdirenv.services

import com.intellij.openapi.components.Service
import systems.fehn.intellijdirenv.MyBundle

@Service
class EnvironmentService {
fun unsetVariable(name: String) {
modifiableEnvironment.remove(name)
Expand Down
9 changes: 5 additions & 4 deletions src/main/resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!-- Plugin Configuration File. Read more: https://plugins.jetbrains.com/docs/intellij/plugin-configuration-file.html -->
<idea-plugin url="https://github.com/fehnomenal/intellij-direnv">
<id>systems.fehn.intellijdirenv</id>
<name>Direnv integration</name>
<name>Direnv Integration</name>
<vendor>fehnomenal</vendor>

<depends>com.intellij.modules.platform</depends>
Expand All @@ -11,9 +11,6 @@
id="systems.fehn.intellijdirenv.settings.DirenvSettingsConfigurable"
displayName="Direnv Settings" />
<applicationService serviceImplementation="systems.fehn.intellijdirenv.settings.DirenvSettingsState" />
<applicationService serviceImplementation="systems.fehn.intellijdirenv.services.EnvironmentService" />
<projectService serviceImplementation="systems.fehn.intellijdirenv.services.DirenvProjectService" />

<notificationGroup id="Direnv" displayType="BALLOON" />
<postStartupActivity implementation="systems.fehn.intellijdirenv.MyStartupActivity" />
</extensions>
Expand All @@ -32,4 +29,8 @@
relative-to-action="SynchronizeCurrentFile" />
</action>
</actions>
<projectListeners>
<listener class="systems.fehn.intellijdirenv.DirenvExecutionListener"
topic="com.intellij.execution.ExecutionListener" />
</projectListeners>
</idea-plugin>

0 comments on commit 0d035aa

Please sign in to comment.