In fish array ranges are one-based and inclusive of both extremes, which, unsurprisingly, leads to problems when possibly-zero-length-ranges are required.
In particular, I'm in a situation where I split out the first arguments for my own consumption, and I want to forward the rest of them - which may be none! - to some command. If this was Python, I could do something like:
my_arg = sys.argv[1]
other_args = sys.argv[2:]
However, the straight translation of this to fish unfortunately doesn't work in edge cases; consider
set -l my_arg $argv[1]
set -l other_args $argv[2..-1]
(I kept the same indexes as, while in fish indexing is 1-based, $argv
doesn't include what would be sys.argv[0]
)
This works fine as long as there are enough arguments; for example, if I invoke my command with arguments a b c d e
I'll get $my_arg = a
and $other_args = b c d e
.
However, if I invoke it with just a
, other_args
will be surprisingly set to a
as well. This comes from the fact that -1
actually gets expanded to something to the effect of (count $argv)
, so the statement above is equivalent to
set -l other_args $argv[2..1]
which is an inverted range from the nonexistent element 2 to the existent element 1, inclusive, which boils down to plain $argv[1]
.
To avoid this problem, currently I'm using this horrible workaround
set -l other_args $argv[2..(expr (count $argv) + 1)]
which ensures that the last index is one past the last, forcing the range to be a "straight" one, albeit possibly fully out of range (which returns an empty list as required).
However, I'm wondering: is there a better solution that I'm missing?
However, I'm wondering: is there a better solution that I'm missing?
Upgrade to 3.0. This was a bug in 2.7 that is fixed there.
The way this works now is that, if only one of the indices in a range is negative, it'll always be interpreted as the larger of the two, so with a negative end, iteration is forced to go forward.
If the index isn't actually larger, this results in no elements instead, which is precisely what you want here.