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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,5 @@ tags
# Ignore
result
ref
.env
.env.local
2 changes: 1 addition & 1 deletion home-manager/programs/fish/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
fish_add_path -p /etc/profiles/per-user/${config.home.username}/bin
'';
interactiveShellInit = ''
# disable fish greeting
__hm_load_env_file
set fish_greeting
set fish_theme dracula
fish_add_path -p ~/.nix-profile/bin
Expand Down
46 changes: 46 additions & 0 deletions home-manager/programs/fish/functions/__hm_load_env_file.fish
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
function __hm_load_env_file --description 'Load environment variables from .env'
set -l candidate_paths
if set -q DOTFILES_ENV_FILE
set -a candidate_paths $DOTFILES_ENV_FILE
end
set -a candidate_paths $HOME/dotfiles/.env $HOME/.env

set -l env_file
for candidate in $candidate_paths
if test -f $candidate
set env_file $candidate
break
end
end

if test -z "$env_file"
return
end

while read -l line
set -l trimmed (string trim $line)
if test -z "$trimmed"
continue
end
if string match -qr '^#' -- $trimmed
continue
end

set trimmed (string replace -r '^export\\s+' '' -- $trimmed)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The regular expression to remove the export prefix is incorrect. The double backslash in \\s+ will be treated as a literal backslash followed by s, so it won't match whitespace. To match one or more whitespace characters in a PCRE regex used by fish, you should use \s+.

    set trimmed (string replace -r '^export\s+' '' -- $trimmed)

set -l parts (string split -m2 '=' -- $trimmed)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The option -m2 for string split is invalid syntax in fish shell and will cause the script to fail. To split the line only on the first occurrence of =, you should use the option -m 1. This will correctly separate the key from the value, which is crucial for parsing lines where the value itself might contain an equals sign (e.g., DATABASE_URL=postgres://...).

    set -l parts (string split -m 1 '=' -- $trimmed)

if test (count $parts) -lt 2
continue
end
Comment on lines +29 to +33

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix regex stripping export.

^export\\s+ matches the literal string export\s instead of whitespace, so .env lines that start with export keep the prefix and later try to set a variable named export. Fixing the regex to ^export\s+ correctly removes the prefix.

Apply this diff:

-    set trimmed (string replace -r '^export\\s+' '' -- $trimmed)
+    set trimmed (string replace -r '^export\s+' '' -- $trimmed)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
set trimmed (string replace -r '^export\\s+' '' -- $trimmed)
set -l parts (string split -m2 '=' -- $trimmed)
if test (count $parts) -lt 2
continue
end
set trimmed (string replace -r '^export\s+' '' -- $trimmed)
set -l parts (string split -m2 '=' -- $trimmed)
if test (count $parts) -lt 2
continue
end
🤖 Prompt for AI Agents
home-manager/programs/fish/functions/__hm_load_env_file.fish around lines 29-33:
the regex used in string replace is escaping the backslash so it matches a
literal "\s" rather than whitespace; change the regex from '^export\\s+' to
'^export\s+' so the pattern correctly strips the "export" prefix followed by any
whitespace from the start of the line.


set -l key (string trim $parts[1])
set -l value (string trim $parts[2])

Comment on lines +29 to +37

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] Strip export prefix before parsing keys

The regex used to drop an optional export prefix is '^export\\s+', which matches a literal \s string instead of whitespace because the backslash is escaped twice. Lines like export FOO=bar therefore leave trimmed as export FOO=bar, and the subsequent set -gx assigns a variable named export with values FOO and bar rather than exporting FOO. .env files that include the export keyword will silently fail to load the intended variables. Use '^export\s+' or '^export\s+' with a single backslash so the whitespace is removed before splitting.

Useful? React with 👍 / 👎.

if string match -qr "^'.*'\z" -- $value
set value (string trim --chars "'" -- $value)
else if string match -qr '^".*"$' -- $value
set value (string trim --chars '"' -- $value)
end
Comment on lines +38 to +42

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using string trim --chars to remove quotes can be unreliable. For example, a value like ''foo'' would be incorrectly trimmed to foo instead of the intended 'foo'. A more robust approach is to use string sub --start=2 --end=-2, which removes only the first and last characters.

Additionally, the regex for matching double-quoted strings uses $ to match the end of the line. It's better practice to use \z to match the end of the string, which is more accurate if values span multiple lines.

    if string match -qr "^'.*'\z" -- $value
      set value (string sub --start=2 --end=-2 -- $value)
    else if string match -qr '^\".*\"\z' -- $value
      set value (string sub --start=2 --end=-2 -- $value)
    end


set -gx $key $value
end < $env_file
Comment on lines +44 to +45

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Preserve whitespace in values when exporting.

Without quoting, any spaces in the value become separate list elements (e.g., FOO="hello world" becomes two words). Quoting the value and stopping option parsing keeps the original string intact.

Apply this diff:

-    set -gx $key $value
+    set -gx -- $key "$value"
🤖 Prompt for AI Agents
In home-manager/programs/fish/functions/__hm_load_env_file.fish around lines
44-45, the export uses set -gx $key $value which can split values containing
spaces; change it to use a stop-opts marker and quoted value: set -gx -- $key
"$value" so option parsing is disabled and the original string (including
whitespace) is preserved when exporting.

end
2 changes: 1 addition & 1 deletion rules
Submodule rules updated from b140aa to bf5e1f