blog: add "Using direnv in PowerShell on Windows" post
This commit is contained in:
parent
b6824ce67f
commit
5ab4c269d1
1 changed files with 138 additions and 0 deletions
138
src/content/blog/using-direnv-in-powershell-on-windows.md
Normal file
138
src/content/blog/using-direnv-in-powershell-on-windows.md
Normal file
|
|
@ -0,0 +1,138 @@
|
|||
---
|
||||
title: "Using direnv in PowerShell on Windows"
|
||||
description: "Simple way to manage environment variables in PowerShell on Windows"
|
||||
date: 2026-02-17T12:50:32+07:00
|
||||
draft: false
|
||||
tags:
|
||||
- script
|
||||
- windows
|
||||
---
|
||||
|
||||
# Background
|
||||
|
||||
I want a `direnv` functionality in PowerShell running in Windows. Using the [official direnv](https://direnv.net/docs/installation.html) introduces problems because of platform compatibility (Unix-based vs Windows). So I decided to make a PowerShell script to load (and unload) `.envrc` file automatically just like `direnv` does.
|
||||
|
||||
# How to Use
|
||||
|
||||
- save the `direnv` script below to `$PROFILE\Scripts\direnv.ps1`.
|
||||
- add `. "$PSScriptRoot\Scripts\direnv.ps1"` line to `$PROFILE` to load it.
|
||||
|
||||
# Script
|
||||
|
||||
```powershell
|
||||
# PowerShell direnv alternative - Add to $PROFILE
|
||||
|
||||
# Global variables to track state
|
||||
$global:EnvrcLoadedVars = @{}
|
||||
$global:LastEnvrcPath = $null
|
||||
|
||||
function Load-Envrc {
|
||||
param (
|
||||
[string]$Path
|
||||
)
|
||||
|
||||
$envrcFile = Join-Path $Path ".envrc"
|
||||
|
||||
if (Test-Path $envrcFile) {
|
||||
# If we're loading the same .envrc, skip
|
||||
if ($global:LastEnvrcPath -eq $envrcFile) {
|
||||
return
|
||||
}
|
||||
|
||||
# Unload previous environment variables
|
||||
Unload-Envrc
|
||||
|
||||
Write-Host "direnv: loading $envrcFile" -ForegroundColor Green
|
||||
|
||||
# Read and parse .envrc file
|
||||
Get-Content $envrcFile | ForEach-Object {
|
||||
$line = $_.Trim()
|
||||
|
||||
# Skip empty lines and comments
|
||||
if ($line -eq "" -or $line.StartsWith("#")) {
|
||||
return
|
||||
}
|
||||
|
||||
# Match export VAR=value or export VAR="value"
|
||||
if ($line -match '^export\s+([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.+)$') {
|
||||
$varName = $matches[1]
|
||||
$varValue = $matches[2]
|
||||
|
||||
# Remove quotes if present
|
||||
$varValue = $varValue -replace '^["'']|["'']$', ''
|
||||
|
||||
# Store the original value (if it exists) so we can restore it
|
||||
if (Test-Path "env:$varName") {
|
||||
$global:EnvrcLoadedVars[$varName] = @{
|
||||
Original = (Get-Item "env:$varName").Value
|
||||
HasOriginal = $true
|
||||
}
|
||||
} else {
|
||||
$global:EnvrcLoadedVars[$varName] = @{
|
||||
Original = $null
|
||||
HasOriginal = $false
|
||||
}
|
||||
}
|
||||
|
||||
# Set the environment variable
|
||||
Set-Item -Path "env:$varName" -Value $varValue
|
||||
Write-Host " export $varName" -ForegroundColor Gray
|
||||
}
|
||||
}
|
||||
|
||||
# Track the current .envrc path
|
||||
$global:LastEnvrcPath = $envrcFile
|
||||
}
|
||||
else {
|
||||
# No .envrc in current directory, unload if we had one loaded
|
||||
if ($global:LastEnvrcPath -ne $null) {
|
||||
Unload-Envrc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function Unload-Envrc {
|
||||
if ($global:EnvrcLoadedVars.Count -gt 0) {
|
||||
Write-Host "direnv: unloading" -ForegroundColor Yellow
|
||||
|
||||
foreach ($varName in $global:EnvrcLoadedVars.Keys) {
|
||||
$varInfo = $global:EnvrcLoadedVars[$varName]
|
||||
|
||||
if ($varInfo.HasOriginal) {
|
||||
# Restore original value
|
||||
Set-Item -Path "env:$varName" -Value $varInfo.Original
|
||||
} else {
|
||||
# Remove the variable as it didn't exist before
|
||||
Remove-Item -Path "env:$varName" -ErrorAction SilentlyContinue
|
||||
}
|
||||
}
|
||||
|
||||
$global:EnvrcLoadedVars = @{}
|
||||
$global:LastEnvrcPath = $null
|
||||
}
|
||||
}
|
||||
|
||||
# Hook into directory change
|
||||
$global:LastDirectory = $PWD.Path
|
||||
|
||||
function Invoke-EnvrcCheck {
|
||||
if ($PWD.Path -ne $global:LastDirectory) {
|
||||
$global:LastDirectory = $PWD.Path
|
||||
Load-Envrc -Path $PWD.Path
|
||||
}
|
||||
}
|
||||
|
||||
# Override the prompt to check for .envrc on every command
|
||||
$global:OriginalPrompt = $function:prompt
|
||||
|
||||
function prompt {
|
||||
Invoke-EnvrcCheck
|
||||
& $global:OriginalPrompt
|
||||
}
|
||||
|
||||
# Load .envrc in the current directory when profile loads
|
||||
Load-Envrc -Path $PWD.Path
|
||||
|
||||
Write-Host "direnv-like functionality loaded. .envrc files will be auto-loaded/unloaded on directory change." -ForegroundColor Cyan
|
||||
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue