I have carefully read the fish shell documentation, and I am trying to figure out how to conditionally set a local variable in a fish function.
In other words, if you have a function and you want a local variable to be modified with if-then-else logic.
function foo
set --local variable something
if blah
set --local variable something_else
end
end
For instance, assume I have a trivial function that accepts a filename as an argument, and if the file extension is missing, I want to add it to the argument.
function frob
set --local filename $argv[1]
echo "Before: $filename"
if not string match --regex --entire "\.fish" $filename
set --local filename $filename.fish
end
echo "After: $filename"
end
The problem is that since local variables only have block scope, this does not work. Running that "frob" function just prints the same thing in both the "Before" and "After".
The only work-around I can think of is to use a temporary global variable, and just manually delete it at the end of the function.
Example:
function frob
# Use global variable, and try to handle collisions
if set --query --global filename
set --global filename_saved $filename
end
set --global filename $argv[1]
echo "Before: $filename"
if not string match --regex --entire "\.fish" $filename
set --global filename $filename.fish
end
echo "After: $filename"
# Restore old saved value
if set --query --global filename_saved
set --global filename $filename_saved
set --erase --global filename_saved
else
set --global --erase filename
end
end
There are a couple of issues with this method, however. First of all, I would want to check for possible collisions with a preexisting global variable, and save any existing value to be restored when my script exits.
Unfortunately, if my script ends unexpectedly due to an error, it is possible that the "cleanup" code will never be executed.
Am I missing some better way to approach this problem?
"local" is a bit of a misnomer. It's "block-scoped".
That means when you do
begin
set -l foo
end
$foo
is only defined in that block.
And something like
set -l foo
begin
set -l foo
end
will create a second version of $foo
inside that block, and return to the other once the block ends.
So, what you need to do is to define it outside of the block and then just change it inside:
set -l foo
begin
set foo bar
end
i.e.
function frob
set --local filename $argv[1]
echo "Before: $filename"
if not string match --regex --entire "\.fish" $filename
set filename $filename.fish
end
echo "After: $filename"
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With