From a8f5969b94412e9831f44b400f255687bf531aa5 Mon Sep 17 00:00:00 2001
From: David Ringle
Date: Thu, 17 Jul 2025 15:42:37 +0300
Subject: [PATCH 1/7] For now, allowing only one command for laravel
---
.../visualenv/profile/LaravelProfile.java | 26 +++++++++----------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/src/main/java/com/ringlesoft/visualenv/profile/LaravelProfile.java b/src/main/java/com/ringlesoft/visualenv/profile/LaravelProfile.java
index f0ccbe8..ee46daf 100644
--- a/src/main/java/com/ringlesoft/visualenv/profile/LaravelProfile.java
+++ b/src/main/java/com/ringlesoft/visualenv/profile/LaravelProfile.java
@@ -467,19 +467,19 @@ public List getAvailableCliActions() {
"Generate a new application key and store it in the .env file"
).addEnvironmentVariable("ENV_FILE", "{selectedEnvFile}"),
- new CliActionDefinition(
- "artisan_env_encrypt",
- "Encrypt Environment File",
- "php artisan env:encrypt",
- "Encrypts an environment file variable using the Laravel framework"
- ).addParameter(
- new CliParameterDefinition(
- "name",
- "Variable Name",
- "Name of the environment variable to retrieve",
- true
- )
- ),
+// new CliActionDefinition(
+// "artisan_env_encrypt",
+// "Encrypt Environment File",
+// "php artisan env:encrypt",
+// "Encrypts an environment file variable using the Laravel framework"
+// ).addParameter(
+// new CliParameterDefinition(
+// "name",
+// "Variable Name",
+// "Name of the environment variable to retrieve",
+// true
+// )
+// ),
};
return Arrays.asList(definitions);
}
From c7a1d66b0b667e461a76a1f7ef7b6216636ee695 Mon Sep 17 00:00:00 2001
From: David Ringle
Date: Thu, 17 Jul 2025 15:51:05 +0300
Subject: [PATCH 2/7] More cleaning
---
.../visualenv/model/EnvVariableDefinition.java | 1 -
.../ringlesoft/visualenv/profile/LaravelProfile.java | 12 ++++++++++--
.../visualenv/services/EnvFileService.java | 12 +++++-------
.../visualenv/services/ProjectService.java | 4 ----
.../visualenv/toolWindow/CliActionsTab.java | 7 +++----
.../visualenv/toolWindow/EnvEditorTab.java | 4 ++--
.../ringlesoft/visualenv/utils/CommandRunner.java | 4 +---
src/main/resources/icons/pluginicon.svg | 2 +-
src/main/resources/messages/MyBundle.properties | 2 +-
9 files changed, 23 insertions(+), 25 deletions(-)
diff --git a/src/main/java/com/ringlesoft/visualenv/model/EnvVariableDefinition.java b/src/main/java/com/ringlesoft/visualenv/model/EnvVariableDefinition.java
index 1937637..8c0786c 100644
--- a/src/main/java/com/ringlesoft/visualenv/model/EnvVariableDefinition.java
+++ b/src/main/java/com/ringlesoft/visualenv/model/EnvVariableDefinition.java
@@ -1,6 +1,5 @@
package com.ringlesoft.visualenv.model;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
diff --git a/src/main/java/com/ringlesoft/visualenv/profile/LaravelProfile.java b/src/main/java/com/ringlesoft/visualenv/profile/LaravelProfile.java
index ee46daf..8fb76a8 100644
--- a/src/main/java/com/ringlesoft/visualenv/profile/LaravelProfile.java
+++ b/src/main/java/com/ringlesoft/visualenv/profile/LaravelProfile.java
@@ -1,7 +1,6 @@
package com.ringlesoft.visualenv.profile;
import com.ringlesoft.visualenv.model.CliActionDefinition;
-import com.ringlesoft.visualenv.model.CliParameterDefinition;
import com.ringlesoft.visualenv.model.EnvFileDefinition;
import com.ringlesoft.visualenv.model.EnvVariableDefinition;
@@ -24,7 +23,7 @@ public class LaravelProfile implements EnvProfile {
public static final String GROUP_MAIL = "mail";
public static final String GROUP_PUSHER = "pusher";
public static final String GROUP_AWS = "aws";
- public static final String GROUP_REDIS = "redis";
+ public static final String GROUP_DEBUG = "redis";
public static final String GROUP_VITE_PUSHER = "vite_pusher";
private static final Map REGISTRY = new HashMap<>();
@@ -374,6 +373,15 @@ public class LaravelProfile implements EnvProfile {
false
);
+ register(
+ "DEBUGBAR_ENABLED",
+ "Enable or Disable Laravel Debug-bar",
+ null,
+ EnvVariableDefinition.VariableType.BOOLEAN,
+ GROUP_DEBUG,
+ false
+ );
+
EnvVariableDefinition appKey = REGISTRY.get("APP_KEY");
if (appKey != null) {
diff --git a/src/main/java/com/ringlesoft/visualenv/services/EnvFileService.java b/src/main/java/com/ringlesoft/visualenv/services/EnvFileService.java
index 36fc0ad..fea03fb 100644
--- a/src/main/java/com/ringlesoft/visualenv/services/EnvFileService.java
+++ b/src/main/java/com/ringlesoft/visualenv/services/EnvFileService.java
@@ -206,11 +206,11 @@ public boolean createEnvFromTemplate(VirtualFile templateFile) {
EnvVariableDefinition definition = variableRegistry.getVariableDefinition(key);
if (definition != null && definition.isSecret()) {
// Generate a random string for secret values
- value = generateRandomString(32);
+ value = generateRandomString();
} else if (value.isEmpty() || value.equals("null") ||
(key.toLowerCase().contains("key") && !key.toLowerCase().contains("keyboard"))) {
// Heuristic: if it has "key" in the name but no value, randomize it
- value = generateRandomString(32);
+ value = generateRandomString();
}
newContent.append(key).append('=').append(value).append('\n');
@@ -276,15 +276,14 @@ public VirtualFile findTemplateFile() {
/**
* Generate a random string for use as a secret key
*
- * @param length Length of the string
* @return Random string
*/
- private String generateRandomString(int length) {
+ private String generateRandomString() {
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*()";
StringBuilder result = new StringBuilder();
Random random = new Random();
- for (int i = 0; i < length; i++) {
+ for (int i = 0; i < 32; i++) {
result.append(characters.charAt(random.nextInt(characters.length())));
}
@@ -358,8 +357,7 @@ public String executeArtisanCommand(String command) {
}
CommandRunner commandRunner = new CommandRunner(project);
- String output = commandRunner.runCommandWithOutput(command);
- return output;
+ return commandRunner.runCommandWithOutput(command);
} catch (Exception e) {
LOG.error("Error executing Artisan command", e);
return "Error: " + e.getMessage();
diff --git a/src/main/java/com/ringlesoft/visualenv/services/ProjectService.java b/src/main/java/com/ringlesoft/visualenv/services/ProjectService.java
index 761dfbc..68bb86b 100644
--- a/src/main/java/com/ringlesoft/visualenv/services/ProjectService.java
+++ b/src/main/java/com/ringlesoft/visualenv/services/ProjectService.java
@@ -104,10 +104,6 @@ private void scanAndProcessEnvFiles(@NotNull Project project, EnvProfile profile
foundFiles.add(envFile);
}
}
-
- if (foundFiles.isEmpty()) {
- // TODO show
- }
}
public CommandRunner getCommandRunner() {
diff --git a/src/main/java/com/ringlesoft/visualenv/toolWindow/CliActionsTab.java b/src/main/java/com/ringlesoft/visualenv/toolWindow/CliActionsTab.java
index 9525863..e595c85 100644
--- a/src/main/java/com/ringlesoft/visualenv/toolWindow/CliActionsTab.java
+++ b/src/main/java/com/ringlesoft/visualenv/toolWindow/CliActionsTab.java
@@ -20,7 +20,7 @@ public class CliActionsTab extends JPanel {
private final EnvFileService envService;
private final EnvProfile profile;
private JTextArea resultArea; // Added field for displaying results
-
+
/**
* Create a new Artisan tab
*
@@ -147,8 +147,7 @@ private void addProfileCommands(JPanel panel) {
*/
private void executeCliAction(CliActionDefinition action) {
String command = action.getCommand();
- String result = "";
-
+
if (action.isRequiresUserInput()) {
// Get parameters
List parameters = action.getParameters();
@@ -173,7 +172,7 @@ private void executeCliAction(CliActionDefinition action) {
}
// Execute the command
- result = envService.executeArtisanCommand(command);
+ String result = envService.executeArtisanCommand(command);
displayCommandResult(result, action.getName() + " Result");
}
diff --git a/src/main/java/com/ringlesoft/visualenv/toolWindow/EnvEditorTab.java b/src/main/java/com/ringlesoft/visualenv/toolWindow/EnvEditorTab.java
index 79a5efc..6914ab8 100644
--- a/src/main/java/com/ringlesoft/visualenv/toolWindow/EnvEditorTab.java
+++ b/src/main/java/com/ringlesoft/visualenv/toolWindow/EnvEditorTab.java
@@ -41,7 +41,7 @@ public class EnvEditorTab extends JPanel implements AutoCloseable {
private final Map groupPanels = new HashMap<>();
private VirtualFile selectedEnvFile;
private final Map fileBasenameToPath = new HashMap<>();
- private FileSaveListener fileSaveListener;
+ private final FileSaveListener fileSaveListener;
/**
* Create a new Environment editor tab
@@ -367,7 +367,7 @@ public void reloadCurrentEnvFile() {
}
@Override
- public void close() throws Exception {
+ public void close() {
fileSaveListener.dispose();
}
diff --git a/src/main/java/com/ringlesoft/visualenv/utils/CommandRunner.java b/src/main/java/com/ringlesoft/visualenv/utils/CommandRunner.java
index ea60191..6cd7168 100644
--- a/src/main/java/com/ringlesoft/visualenv/utils/CommandRunner.java
+++ b/src/main/java/com/ringlesoft/visualenv/utils/CommandRunner.java
@@ -34,8 +34,6 @@ public void runCommand(String command, ProcessListener processListener) {
String[] args = new String[parts.length - 2];
System.arraycopy(parts, 2, args, 0, args.length);
runCommandWithOutput(parts[0], parts[1], args, (processListener != null) ? processListener : outputHandler());
- } else {
-
}
}
@@ -156,7 +154,7 @@ public void processTerminated(@NotNull ProcessEvent event) {
Notifications.Bus.notify(new Notification(
"Visual Env Notification Group",
"Error",
- "Failed to execute command: " + output.toString(),
+ "Failed to execute command: " + output,
NotificationType.ERROR
), project);
}
diff --git a/src/main/resources/icons/pluginicon.svg b/src/main/resources/icons/pluginicon.svg
index 91dd293..3843309 100644
--- a/src/main/resources/icons/pluginicon.svg
+++ b/src/main/resources/icons/pluginicon.svg
@@ -1,5 +1,5 @@
-
- Key Features:
-
- - Environment Variable Management - View, edit, and organize environment variables from .env files
- - Framework Detection - Automatically detects Laravel projects and adapts to project-specific settings
- - Type-Aware Interface - Specialized UI controls for different variable types (toggles for booleans, dropdowns for enums)
- - CLI Command Integration - Run framework-specific commands directly from the IDE
- - Smart Organization - Group variables by category for better navigation
- - Template Support - Create new .env files from .env.example templates with one click
-
-
-
- Framework Support:
-
- - Laravel - Full support with predefined variables and artisan command integration
- - More frameworks coming soon!
-
+ Streamline environment variable management across your projects with an intuitive interface that adapts to your development framework.
+ Core Features:
+
+ - Smart .env Management - Edit variables with type-aware controls (toggles, dropdowns, validation)
+ - Framework Integration - Auto-detects Laravel projects with predefined variables and artisan commands
+ - Quick Setup - Generate .env files from templates and organize variables by category
+ - CLI Integration - Execute framework commands (php artisan key:generate) directly from the IDE
+
+ Supported Frameworks: Laravel, Node.js, Django, Generic (with more coming soon)
]]>
com.intellij.modules.platform
From 2efdbc9edba022f51bf2cab9cacc6f238808b794 Mon Sep 17 00:00:00 2001
From: David Ringle
Date: Thu, 17 Jul 2025 17:02:11 +0300
Subject: [PATCH 5/7] Safe formating of keys and values
---
.../visualenv/services/EnvFileService.java | 20 -------------------
.../visualenv/utils/EnvFileManager.java | 17 ++++++++++++++++
2 files changed, 17 insertions(+), 20 deletions(-)
diff --git a/src/main/java/com/ringlesoft/visualenv/services/EnvFileService.java b/src/main/java/com/ringlesoft/visualenv/services/EnvFileService.java
index d93c025..8aba353 100644
--- a/src/main/java/com/ringlesoft/visualenv/services/EnvFileService.java
+++ b/src/main/java/com/ringlesoft/visualenv/services/EnvFileService.java
@@ -118,9 +118,6 @@ public boolean updateEnvVariable(String name, String value) {
}
try {
- if (value.contains(" ")) {
- value = "\"" + value + "\"";
- }
// Use EnvFileManager to update the variable
EnvFileManager.setEnvVariable(project, activeEnvFile, name, value);
// Update cache
@@ -607,23 +604,6 @@ public String getLastUpdatedVariable() {
*/
public boolean addVariable(String key, String value) {
try {
- key = key.trim()
- .replaceAll("\\s+", "_") // spaces to underscores
- .replaceAll("[^a-zA-Z0-9_]", "_") // special chars to underscores
- .replaceAll("_{2,}", "_") // multiple underscores to single
- .replaceAll("^[0-9_]+", "") // remove leading numbers/underscores
- .toUpperCase();
-
- value = value.replace("\\", "\\\\")
- .replace("\"", "\\\"")
- .replace("\n", "\\n")
- .replace("\r", "\\r");
-
- // Quote if contains spaces, special chars, or starts with quote
- if (value.matches(".*[\\s#'`${}()].*") || value.startsWith("\"")) {
- value = "\"" + value + "\"";
- }
-
EnvFileManager.setEnvVariable(project, activeEnvFile, key, value);
return true;
} catch (Exception e) {
diff --git a/src/main/java/com/ringlesoft/visualenv/utils/EnvFileManager.java b/src/main/java/com/ringlesoft/visualenv/utils/EnvFileManager.java
index 651e12b..e2b6135 100644
--- a/src/main/java/com/ringlesoft/visualenv/utils/EnvFileManager.java
+++ b/src/main/java/com/ringlesoft/visualenv/utils/EnvFileManager.java
@@ -803,6 +803,16 @@ public static boolean restoreBackup(Project project, VirtualFile directory, Stri
* @param value Env variable value
*/
private static void setEnvVariableInternal(@NotNull Document document, String key, String value) {
+
+ value = value.replace("\\", "\\\\")
+ .replace("\"", "\\\"")
+ .replace("\n", "\\n")
+ .replace("\r", "\\r");
+ // Quote if contains spaces, special chars, or starts with quote
+ if (value.matches(".*[\\s#'`${}()].*") || value.startsWith("\"")) {
+ value = "\"" + value + "\"";
+ }
+
try {
String documentText = document.getText();
String newLine = key + "=" + value;
@@ -815,6 +825,13 @@ private static void setEnvVariableInternal(@NotNull Document document, String ke
int end = matcher.end();
document.replaceString(start, end, newLine);
} else {
+ key = key.trim()
+ .replaceAll("\\s+", "_") // spaces to underscores
+ .replaceAll("[^a-zA-Z0-9_]", "_") // special chars to underscores
+ .replaceAll("_{2,}", "_") // multiple underscores to single
+ .replaceAll("^[0-9_]+", "") // remove leading numbers/underscores
+ .toUpperCase();
+ newLine = key + "=" + value;
if (!documentText.isEmpty() && !documentText.endsWith("\n")) {
newLine = "\n" + newLine;
}
From 19889471774905eafb290120ae1dc3cad5dd0fab Mon Sep 17 00:00:00 2001
From: David Ringle
Date: Thu, 17 Jul 2025 18:02:19 +0300
Subject: [PATCH 6/7] Improved context menu actions for Env variables
---
.../visualenv/model/EnvVariable.java | 2 +-
.../visualenv/services/EnvFileService.java | 25 +++
.../visualenv/toolWindow/EnvGroupPanel.java | 154 +++++++++++++++++-
.../visualenv/utils/EnvFileManager.java | 2 +
.../services/EnvFileServiceTest.java | 2 +-
5 files changed, 180 insertions(+), 5 deletions(-)
diff --git a/src/main/java/com/ringlesoft/visualenv/model/EnvVariable.java b/src/main/java/com/ringlesoft/visualenv/model/EnvVariable.java
index e16b497..ab70aa9 100644
--- a/src/main/java/com/ringlesoft/visualenv/model/EnvVariable.java
+++ b/src/main/java/com/ringlesoft/visualenv/model/EnvVariable.java
@@ -31,7 +31,7 @@ public String getName() {
}
public String getValue() {
- return isSecret ? "********" : value;
+ return isSecret ? "*".repeat(value.length()) : value;
}
public String getRawValue() {
diff --git a/src/main/java/com/ringlesoft/visualenv/services/EnvFileService.java b/src/main/java/com/ringlesoft/visualenv/services/EnvFileService.java
index 8aba353..a6891bd 100644
--- a/src/main/java/com/ringlesoft/visualenv/services/EnvFileService.java
+++ b/src/main/java/com/ringlesoft/visualenv/services/EnvFileService.java
@@ -604,10 +604,35 @@ public String getLastUpdatedVariable() {
*/
public boolean addVariable(String key, String value) {
try {
+ key = key.trim()
+ .replaceAll("\\s+", "_") // Replace spaces with underscores
+ .replaceAll("[^a-zA-Z0-9_]", "_") // Remove non-alphanumeric characters
+ .toUpperCase();
EnvFileManager.setEnvVariable(project, activeEnvFile, key, value);
return true;
} catch (Exception e) {
return false;
}
}
+
+ public boolean deleteEnvVariable(String variableName) {
+ try {
+ EnvFileManager.removeEnvVariable(project, activeEnvFile, variableName);
+ return true;
+ } catch (Exception e) {
+ return false;
+ }
+ }
+
+ public boolean renameVariable(String variableName, String newName) {
+ try {
+ newName = newName.trim()
+ .replaceAll("\\s+", "_") // Replace spaces with underscores
+ .replaceAll("[^a-zA-Z0-9_]", "_") // Remove non-alphanumeric characters
+ .toUpperCase();
+ return EnvFileManager.renameEnvVariable(project, activeEnvFile, variableName, newName);
+ } catch (Exception e) {
+ return false;
+ }
+ }
}
diff --git a/src/main/java/com/ringlesoft/visualenv/toolWindow/EnvGroupPanel.java b/src/main/java/com/ringlesoft/visualenv/toolWindow/EnvGroupPanel.java
index 3ce7996..cd07e8a 100644
--- a/src/main/java/com/ringlesoft/visualenv/toolWindow/EnvGroupPanel.java
+++ b/src/main/java/com/ringlesoft/visualenv/toolWindow/EnvGroupPanel.java
@@ -1,6 +1,8 @@
package com.ringlesoft.visualenv.toolWindow;
+import com.intellij.icons.AllIcons;
import com.intellij.openapi.ui.ComboBox;
+import com.intellij.util.ui.JBUI;
import com.ringlesoft.visualenv.model.EnvVariable;
import com.ringlesoft.visualenv.model.EnvVariableDefinition;
import com.ringlesoft.visualenv.services.EnvFileService;
@@ -12,7 +14,10 @@
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import java.awt.*;
+import java.awt.datatransfer.StringSelection;
import java.awt.event.ItemEvent;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -106,14 +111,63 @@ private JPanel createControlForVariable(EnvVariable variable) {
JPanel panel = new JPanel(new BorderLayout(10, 0));
panel.setAlignmentX(Component.LEFT_ALIGNMENT);
panel.setBorder(VisualEnvTheme.VARIABLE_PANEL_BORDER);
-
+
// Create variable name label
JLabel nameLabel = new JLabel(variable.getName() + ":");
nameLabel.setFont(nameLabel.getFont().deriveFont(Font.PLAIN, nameLabel.getFont().getSize() - 1));
nameLabel.setBorder(VisualEnvTheme.VARIABLE_NAME_BORDER);
nameLabel.setToolTipText(getDescriptionForVariable(variable));
+
+ // Add right-click context menu
+ JPopupMenu contextMenu = new JPopupMenu();
+
+ JMenuItem copyItem = new JMenuItem("Copy Variable Name");
+ copyItem.setIcon(AllIcons.Actions.Copy);
+ copyItem.setHorizontalAlignment(SwingConstants.LEFT);
+ copyItem.setPreferredSize(new Dimension(180, 30));
+ copyItem.addActionListener(e -> {
+ Toolkit.getDefaultToolkit().getSystemClipboard().setContents(
+ new StringSelection(variable.getName()), null);
+ statusUpdater.accept("Variable name copied to clipboard");
+ });
+ contextMenu.add(copyItem);
+
+ JMenuItem renameItem = new JMenuItem("Rename Variable");
+ renameItem.setIcon(AllIcons.Actions.Edit);
+ renameItem.setHorizontalAlignment(SwingConstants.LEFT);
+ renameItem.setPreferredSize(new Dimension(180, 30));
+ renameItem.addActionListener(e -> showRenameDialog(variable));
+ contextMenu.add(renameItem);
+
+ JMenuItem deleteItem = new JMenuItem("Delete Variable");
+ deleteItem.setIcon(AllIcons.Actions.GC);
+ deleteItem.setHorizontalAlignment(SwingConstants.LEFT);
+ deleteItem.setPreferredSize(new Dimension(180, 30));
+ deleteItem.addActionListener(e -> {
+ if(envFileService.deleteEnvVariable(variable.getName())){
+ // Remove the variable from the list
+ } else {
+ // failed
+ }
+ });
+
+ // Hover Effect
+ addHoverEffect(copyItem);
+ addHoverEffect(renameItem);
+ addHoverEffect(deleteItem);
+
+ contextMenu.add(deleteItem);
+
+ nameLabel.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mousePressed(MouseEvent e) {
+ if (SwingUtilities.isRightMouseButton(e)) {
+ contextMenu.show(nameLabel, e.getX(), e.getY());
+ }
+ }
+ });
panel.add(nameLabel, BorderLayout.WEST);
-
+
// Create variable value component based on type
Component valueComponent = createControlByType(variable);
panel.add(valueComponent, BorderLayout.CENTER);
@@ -269,7 +323,7 @@ private String getDescriptionForVariable(EnvVariable variable) {
private void updateVariable(String name, String value) {
boolean success = envFileService.updateEnvVariable(name, value);
if (success) {
- statusUpdater.accept("Updated " + name + " to " + (isSecretVariable(name) ? "*****" : value));
+ statusUpdater.accept("Updated " + name + " to " + (isSecretVariable(name) ? "*".repeat(name.length()) : value));
} else {
statusUpdater.accept("Failed to update " + name);
}
@@ -424,4 +478,98 @@ private void updatePanelVisibility(boolean visible) {
variablesPanel.setVisible(visible && expanded);
setVisible(visible && expanded);
}
+
+ private void showRenameDialog(EnvVariable variable) {
+ // Create a modal dialog for adding a new variable
+ JDialog renameDialog = new JDialog();
+ renameDialog.setTitle("Rename " + variable.getName());
+ renameDialog.setModal(true);
+ renameDialog.setLayout(new BorderLayout());
+
+ // Main form panel with proper spacing
+ JPanel formPanel = new JPanel(new GridBagLayout());
+ formPanel.setBorder(JBUI.Borders.empty(20));
+ GridBagConstraints gbc = new GridBagConstraints();
+
+ // Variable Name section
+ gbc.gridx = 0; gbc.gridy = 0;
+ gbc.anchor = GridBagConstraints.WEST;
+ gbc.insets = JBUI.insetsBottom(5);
+ JLabel keyLabel = new JLabel("New Name:");
+ formPanel.add(keyLabel, gbc);
+
+ gbc.gridy = 1;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.weightx = 1.0;
+ gbc.insets = JBUI.insetsBottom(15);
+ JTextField keyField = new JTextField(20);
+ keyField.setText(variable.getName());
+ formPanel.add(keyField, gbc);
+
+ // Message pane for notifications
+ gbc.gridy = 4;
+ gbc.fill = GridBagConstraints.HORIZONTAL;
+ gbc.insets = JBUI.emptyInsets();
+ JLabel messagePane = new JLabel();
+ messagePane.setText("");
+ messagePane.setForeground(UIManager.getColor("Label.disabledForeground"));
+ messagePane.setFont(messagePane.getFont().deriveFont(Font.ITALIC, messagePane.getFont().getSize() - 1f));
+ formPanel.add(messagePane, gbc);
+
+ // Button panel
+ JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
+ buttonPanel.setBorder(JBUI.Borders.empty(10, 15, 15, 15));
+
+ JButton cancelButton = new JButton("Cancel");
+ JButton saveButton = new JButton("Save");
+
+ cancelButton.addActionListener(event -> renameDialog.dispose());
+ saveButton.addActionListener(event -> {
+ String key = keyField.getText();
+ messagePane.setText("");
+ if (key.isEmpty()) {
+ return;
+ }
+ if (envFileService.renameVariable(variable.getName(), key)) {
+ renameDialog.dispose();
+ } else {
+ messagePane.setText("Failed to rename variable");
+ }
+ });
+
+ buttonPanel.add(cancelButton);
+ buttonPanel.add(saveButton);
+ renameDialog.add(formPanel, BorderLayout.CENTER);
+ renameDialog.add(buttonPanel, BorderLayout.SOUTH);
+
+ renameDialog.pack();
+ renameDialog.setSize(350, renameDialog.getHeight()); // Slightly wider for better proportions
+ renameDialog.setLocationRelativeTo(null); // Center on screen
+
+ // Focus the key field
+ keyField.requestFocus();
+ keyField.selectAll();
+ renameDialog.setVisible(true);
+ }
+
+
+ private void addHoverEffect(JMenuItem item) {
+ Color originalBg = item.getBackground();
+ Color hoverBg = VisualEnvTheme.BACKGROUND_HIGHLIGHT;
+
+ item.addMouseListener(new MouseAdapter() {
+ @Override
+ public void mouseEntered(MouseEvent e) {
+ item.setBackground(hoverBg);
+ item.setOpaque(true);
+ }
+
+ @Override
+ public void mouseExited(MouseEvent e) {
+ item.setBackground(originalBg);
+ item.setOpaque(false);
+ }
+ });
+ }
+
}
diff --git a/src/main/java/com/ringlesoft/visualenv/utils/EnvFileManager.java b/src/main/java/com/ringlesoft/visualenv/utils/EnvFileManager.java
index e2b6135..9fecfc1 100644
--- a/src/main/java/com/ringlesoft/visualenv/utils/EnvFileManager.java
+++ b/src/main/java/com/ringlesoft/visualenv/utils/EnvFileManager.java
@@ -75,6 +75,7 @@ public static void removeEnvVariable(Project project, VirtualFile envFile, Strin
int end = matcher.end();
document.deleteString(start, end);
}
+ FileDocumentManager.getInstance().saveDocument(document);
});
}
@@ -458,6 +459,7 @@ public static List validateEnvFile(VirtualFile envFile) {
*/
public static boolean renameEnvVariable(Project project, VirtualFile envFile,
String oldKey, String newKey) {
+ // Convert to uppercase
if (oldKey.equals(newKey)) return true; // No change needed
// Get the current value
diff --git a/src/test/java/com/ringlesoft/visualenv/services/EnvFileServiceTest.java b/src/test/java/com/ringlesoft/visualenv/services/EnvFileServiceTest.java
index 8dde972..ab8a184 100644
--- a/src/test/java/com/ringlesoft/visualenv/services/EnvFileServiceTest.java
+++ b/src/test/java/com/ringlesoft/visualenv/services/EnvFileServiceTest.java
@@ -68,7 +68,7 @@ public void testParseEnvFile() throws IOException {
assertVariable(variables, "APP_NAME", "My Test App");
assertVariable(variables, "DB_HOST", "localhost");
assertVariable(variables, "DB_PORT", "3306");
- assertVariable(variables, "API_KEY", "********");
+ assertVariable(variables, "API_KEY", "*********");
// Check quotes handling
assertVariable(variables, "QUOTED_VALUE", "This is quoted");
From 45f401de511cceb5e760b7f6a8a43685d3589f64 Mon Sep 17 00:00:00 2001
From: David Ringle
Date: Thu, 17 Jul 2025 18:06:52 +0300
Subject: [PATCH 7/7] v1.0.1
---
CHANGELOG.md | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 518ec33..9a7cbe5 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,8 +4,13 @@
## [Unreleased]
-## [1.0.0] - 2025-07-16
+## [1.0.1] - 2025-07-17
+ - Support for adding new environment variables from the Panel
+ - Support for deleting environment variables from the Panel
+ - Support for renaming environment variables from the Panel
+ - Improved error handling and safety checks
+## [1.0.0] - 2025-07-16
- First release
[Unreleased]: https://github.com/ringlesoft/visual-env/compare/v1.0.0...HEAD