3 ms·
It feels a bit more natural once you've bent your mind enough to understand what the shell is doing. The trick is that `test` and even `[` (which is essentiall
by duckerude 8y ago
It feels a bit more natural once you've bent your mind enough to understand what the shell is doing.
The trick is that `test` and even `[` (which is essentially another name for `test`) are ordinary commands, that exist as stand-alone binaries as well as identical-behaving built-ins. They masquerade as syntax, but they're really not. You can even call them from other, non-shell languages:
>>> from subprocess import run
>>> run(('/usr/bin/[', '-n', '', ']'))
CompletedProcess(args=('/usr/bin/[', '-n', '', ']'), returncode=1)
>>> run(('/usr/bin/test', '3', '=', '3'))
CompletedProcess(args=('/usr/bin/test', '3', '=', '3'), returncode=0)
That means that they're not allowed to do anything to variables, because the variables are inside the shell. `test` doesn't see `"$git_branch"`, it only sees the content of the variable.
Per the normal rules, `"$git_branch"` is an empty string iff $git_branch is empty or unset. Leaving the quotes off can do unexpected things, though a lot less so in fish. Using single quotes means you get a literal string, without any substitution.
You're just looking for an empty string anyway, so you might as well use the equality operator instead of digging through the 18 (!) unary flags prescribed by POSIX. So I'd write either `[ "$git_branch" = "" ]` or `test "$git_branch" = ""`. Some implementations support `==` as another way to write `=`, but `=` is standard.
This modularity makes the shell simpler, but it's not exactly sane. I think that providing `[` was a mistake, because it doesn't look like a command, but maybe having `test` as a command is better than having special expression syntax just for these cases.
- faho 8y agoThere are a few misfeatures in `test`, though. For instance, one way to use it is test somestring to test if "somestring" is empty. POSIX mandates that test with exactly one argument succeeds iff that argument is a non-empty string, to allow that. Fish's test is POSIX-conformant. Now, that means that test -n is true! Which is also triggered for test -n $var if $var has 0 elements. This is a problem and should be improved.
- CameronNemo 8y agoalways quote your variables. POSIX won't change this soon, or likely ever.
- buchanae 8y agoThanks for taking the time to explain the details. If we were to start with a clean slate, could we come up with something natural while still having a clean design with respect to commands? Would it be worth it? The fact that those details haven't sunk in after more than a decade points to an opportunity for a better design, I think. For example, I can pick up Go, Java, Perl, PHP, JS, Nim, etc and memorize the if-statement details in about 5 minutes. Whether or not anyone would use such a shell, I don't know.