Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Better document differences from bash #2382

Closed
faho opened this issue Sep 11, 2015 · 25 comments
Closed

Better document differences from bash #2382

faho opened this issue Sep 11, 2015 · 25 comments
Labels
docs An issue/PR that touches or should touch the docs enhancement
Milestone

Comments

@faho
Copy link
Member

faho commented Sep 11, 2015

We should better document fish's differences with bash (and to a lesser degree zsh, because knowledge of bash is common even among zsh users), maybe even to the point of having an entire section in our documentation dedicated to it.

Some of this is already in the FAQ ("!!"), but some isn't.

In #2379 we see that process expansion is one thing (an equivalent to "$!").

There's of course more, but a slight difficulty here is deciding what goes into "different from bash", and what goes into "general tutorial" (which is already geared at converts) - where does "set X Y" vs "X=Y" go? Both? One of them? What about "$argv"?

So the questions are (in a somewhat overlapping manner):

  • Which differences haven't we adequately covered?

and

  • How do we better draw attention to the fact which of fish's slightly different constructs is an equivalent to bash's $thing?
@alphapapa
Copy link

I suggest having a "Fish vs. X" or a "X-to-Fish Translation Dictionary" section in the docs. One of the things I think it should have is a translation table something like this:

Action/Thing Bash Fish
Command substitution $(command) (command)
Exit code of last command $? $status
Logical AND between commands command1 && command2 command1; and command2
PID of self $$ %self
PID of last command $! %last
Redirect STDERR command 2>/dev/null command ^/dev/null
command 2>&1 command 2>&1
Redirect STDOUT command >/dev/null command >/dev/null
Run command in background command & command &
Unset variable unset foo set -e foo
Variable assignment foo=bar set foo bar

Note that it not only lists obvious differences, but also some significant features which are the same. I think this is also very important, e.g. the way Fish also uses command 2>&1 to redirect STDERR to STDOUT.

I think this should complement a general tutorial by being a reference, a resource designed to be quick to scan through and refer to often. The way I imagine people using it is, someone is converting a script from Bash to Fish, and he knows how to do something in Bash, but not in Fish; so he goes to this translation reference, looks for what he would type in Bash, and immediately finds what to do in Fish.

@ghost
Copy link

ghost commented Sep 11, 2015

Good work @alphapapa.

I would love to see this and more work go into here as well.

@alphapapa
Copy link

Well, how about that, I had no idea that was on the Wikipedia page.

@zanchey
Copy link
Member

zanchey commented Sep 12, 2015

The other good reference is http://hyperpolyglot.org/unix-shells

@faho
Copy link
Member Author

faho commented Sep 12, 2015

One of the things I think it should have is a translation table something like this:

There's also some differences that don't quite fit into that table - how about quoting, word-splitting (e.g. for working with arrays/lists)? Or how about the fact that fish currently has no command substitution inside quotes? How about cross-products (i.e. set -l fish flounders catfish; echo $fish" are tasty") where an added space or added quote is very significant?

A table can certainly be included, but it needs some text to go along with it.

@pickfire
Copy link
Contributor

I suggest something like the https://wiki.archlinux.org/index.php/Pacman_rosetta

@JoshCheek
Copy link

Another one that took me a long time to figure out, bash lets you set env vars on a per-command basis with A=B command and fish lets the env command do it with env A=B command I also hit that command-substitution inside quotes thing, eventually asked. I didn't realize the %self, was delegating to subprocesses and asking for parent pid (so yeah, this list seems necessary, esp b/c I just put fish on ~20 newbies computers, and their mentors very well might need to troubleshoot such things with very little knowledge of fish).

@faho faho added the docs An issue/PR that touches or should touch the docs label Sep 18, 2015
@faho faho added this to the fish-future milestone Sep 18, 2015
@faho
Copy link
Member Author

faho commented Sep 18, 2015

Any thoughts on where this doc should be inserted? I'm thinking of making a section in the tutorial for it, though those experienced with a shell may be likely to skip such things.

@ghost
Copy link

ghost commented Sep 18, 2015

The tutorial is where I would look for this table if I was just getting started with fish.

@faho
Copy link
Member Author

faho commented Sep 18, 2015

Okay, I've now made a larger table and added it to the tutorial, but I've then started fighting doxygen - in particular it doesn't want to show "$(command)" and "||" in the table, and will break if a cell in the "Remarks" column is empty

This is what I have now:

If you know Bash , you'll want to know what is different in Fish. So here's the section for you! Note that while this is about bash, much of it will also apply for related shells such as zsh or ksh or dash.

Action/Thing Bash Fish Remarks
Command substitution "$(command)" (command) ...
Command substitution in a string "foo bar $(command)" "foo bar "(command) ...
Process substitution command <(command) command (command \\| psub) ...
Logical AND between commands command1 && command2 command1; and command2 ...
Exit code of last command $? $status ...
Logical NOT ! command not command ...
PID of self $$ \%self ...
PID of last job $! \%last ...
Redirect STDERR command 2>/dev/null command ^/dev/null or command 2>/dev/null ...
Redirect STDERR command 2>&1 command 2>&1 ...
Redirect STDOUT command >/dev/null command >/dev/null ...
Run command in background command & command & ...
Variable assignment foo=bar set foo bar By default bash variables are global, fish variables are function-scoped
Unset variable unset foo set -e foo ...
Check if a variable is defined [[ ${var+_} ]] or [[ -v var ]] (since bash 4.2) set -q foo ...
Check if a function is defined typeset -f function >/dev/null functions -q function ...
Export a variable export foo set -x foo $foo ...
Expand an n-element array/list to n arguments "${var[@]}" $var Bash does wordsplitting again on unquoted array, fish does not
Expand an n-element array/list to 1 argument "${var[*]}" "$var" ...
Remove element from array/list unset foo[1] set -e foo[2] ...
Count the number of elements in an array/list "${#var[@]}" count $var ...
Return the first array/list element "${var[0]}" or $var $var[1] Fish lists start from 1, bash arrays start from 0
if if CONDITION; then COMMAND; fi if CONDITION; COMMAND; end ...
for for VAR in LIST; do COMMAND; done for VAR in LIST; COMMAND; end ...
while while CONDITION; do COMMAND; done while CONDITION; COMMAND; end ...
Arguments to function $* or $@ $argv ...

function definition | | |
Multi-condition if | | |

@GReagle
Copy link
Contributor

GReagle commented Sep 24, 2015

I have submitted several updates, corrections, and additions to http://hyperpolyglot.org/unix-shells in order to make its information about fish more correct and comprehensive, and all of my submissions were accepted. I suggest that we not duplicate its content at all. We can hyperlink to it in fish docs.

@faho
Copy link
Member Author

faho commented Sep 24, 2015

Well, I don't like the idea of linking people to other sites (that may or may not go down or bad or something), and that site still has a few questionable parts.

E.g. "sublist separators" don't mention and in the table, only later on in the full text, which for some reason mentions "pipelines". Now, I'm not sure if zsh does something regarding pipes and conditional execution, but I'm pretty sure in bash ls && ls does not connect stdout of the former to stdin of the latter.

"Interpolating quotes" mentions that command substitutions inside double quotes aren't executed by fish, but in fact no expansion but variable expansion ($var) is performed in double quotes. Then there's plenty of places where the fish entry says "none" because fish doesn't have any built-in syntax to handle it but then it doesn't mention how to do it (like sequences with seq 0 10 instead of {0..10}).

There's other things missing, but my main point stands: I'd rather we have a table that is installed with our docs than link to an external site. (Not that I dislike what they are doing)

@GReagle
Copy link
Contributor

GReagle commented Sep 24, 2015

http://hyperpolyglot.org/unix-shells has a creative commons attribution-sharealike 3.0 license. So if it ever goes down, a copy can be taken over by fish or some other host, but on the other hand, I understand not wanting to rely on an external resource.

@GReagle
Copy link
Contributor

GReagle commented Sep 24, 2015

@faho

Regarding {0..10}, the web page is correct in that fish does not feature sequence brace expansion. It is a table describing the features of the shells, not every way to achieve a goal with external commands. So, arguably, it is accurate. On the other hand, it is arguable that it would be less accurate but more helpful to replace "none" with "seq 0 10". I don't have a preference either way. But if the fish developers prefer "seq 0 10", it can be changed. Like I wrote earlier, I have submitted such changes before and they were accepted. So what's the problem?

@GReagle
Copy link
Contributor

GReagle commented Sep 24, 2015

@faho

The sublist separator section explicitly states that it is using the zsh terminology from the zsh documentation. And it doesn't mention pipes, it mentions pipelines, which is consistent with the terminology in the zsh documentation. It neither states, implies, nor insinuates that && acts like a pipe. Fish doesn't have the concept of sublist separators. So the table is accurate. But I'm not saying that it is flawless, it could probably be improved to be less confusing.

@GReagle
Copy link
Contributor

GReagle commented Sep 24, 2015

Regarding, brace sequence expansion, bash can do the whole alphabet with {a..z} but seq a z does not work. What is a fish user to do?

@faho
Copy link
Member Author

faho commented Sep 24, 2015

It neither states, implies, nor insinuates that && acts like a pipe.

Nope, see the "Pipelines" section above that:

Pipelines are a sequence of simple commands in which the standard output of each command is redirected to the standard input of its successor.

And I can't see how that's true for "&&".

Fish doesn't have the concept of sublist separators

Fish has and and or, which for most purposes do exactly the same thing. Not mentioning them here might be more accurate, but is considerably less helpful. I think it's quite clear here that fish is the most different from the other shells, so squeezing it into that schema is tougher than the rest, but that doesn't mean it should list "none" whenever there's even a slight difference. It should list the fish option and then the difference. (IMHO, anyway)

Regarding, brace sequence expansion, bash can do the whole alphabet with {a..z} but seq a z does not work. What is a fish user to do?

Currently, don't know. You might want to open an issue about that.

@GReagle
Copy link
Contributor

GReagle commented Sep 24, 2015

I see the problem more clearly now. The zsh documentation defines a pipeline as "either a simple command, or a sequence of two or more [pipes]." So when the webpage describes sublist separators, it is using this definition. But as you pointed out, that's not the definition given on the web page above it.

@JoshCheek
Copy link

@faho is that table anywhere we can edit it / copy its source so we can maintain our own?

@pickfire
Copy link
Contributor

pickfire commented Oct 3, 2015

@JoshCheek Maybe add it to the wiki?

@JoshCheek
Copy link

@pickfire I don't know how to access the markdown behind the table, and it looks tedious to look up / format / retype.

@faho
Copy link
Member Author

faho commented Oct 3, 2015

Here's the markdown (github could do with a "show source" option, though contributors can see it regardless because they can edit any comment):

Action/Thing | Bash | Fish | Remarks
------------ | ---- | ---- | -------
Command substitution | `"$(command)"` | `(command)` | ... 
Command substitution in a string | `"foo bar $(command)"` | `"foo bar "(command)` | ... 
Process substitution | `command <(command)` | `command (command \\\| psub)` | ... 
Logical AND between commands | `command1 && command2` | `command1; and command2` | ...
Exit code of last command | `$?` | `$status` | ... 
Logical NOT | `! command` | `not command` | ... 
PID of self | `$$` | `\%self` | ... 
PID of last job | `$!` | `\%last` | ... 
Redirect STDERR | `command 2>/dev/null` | `command ^/dev/null` or `command 2>/dev/null`  | ... 
Redirect STDERR | `command 2>&1` | `command 2>&1` | ... 
Redirect STDOUT | `command >/dev/null` | `command >/dev/null` | ... 
Run command in background | `command &` | `command &` | ... 
Variable assignment | `foo=bar` | `set foo bar` | By default bash variables are global, fish variables are function-scoped 
Unset variable | `unset foo` | `set -e foo` | ... 
Check if a variable is defined | `[[ ${var+_} ]]` or `[[ -v var ]]` (since bash 4.2) | `set -q foo` | ... 
Check if a function is defined | `typeset -f function >/dev/null` | `functions -q function` | ... 
Export a variable | `export foo` | `set -x foo $foo` | ... 
Expand an n-element array/list to n arguments | `"${var[@]}"` | `$var` | Bash does wordsplitting again on unquoted array, fish does not 
Expand an n-element array/list to 1 argument | `"${var[*]}"` | `"$var"` | ... 
Remove element from array/list | `unset foo[1]` | `set -e foo[2]` | ... 
Count the number of elements in an array/list | `"${#var[@]}"` | `count $var` | ... 
Return the first array/list element | `"${var[0]}"` or `$var` | `$var[1]` | Fish lists start from 1, bash arrays start from 0 
if | if CONDITION; then COMMAND; fi | if CONDITION; COMMAND; end | ... 
for | for VAR in LIST; do COMMAND; done | for VAR in LIST; COMMAND; end | ... 
while | while CONDITION; do COMMAND; done | while CONDITION; COMMAND; end | ... 
Arguments to function | `$*` or `$@` | `$argv` | ... 

function definition | | |
Multi-condition if | | |

@JoshCheek
Copy link

@faho ty!

@JoshCheek
Copy link

I added this list to the wiki here: https://github.com/fish-shell/fish-shell/wiki/Shell-Translation-Dictionary


Regarding, brace sequence expansion, bash can do the whole alphabet with {a..z} but seq a z does not work. What is a fish user to do?

Initially this was tongue-in-cheek, but as I think about it, it seems pretty reasonable as the need for such features is very rare, it's not something you'd type frequently even when you used it (you'd C-p, and edit), and the customization ability of Ruby or Perl is going to exceed Fish's.

# delegate to a language with this feature
$ bash -c 'echo {a..z}'
a b c d e f g h i j k l m n o p q r s t u v w x y z

$ perl -e 'print "a".."z"'
abcdefghijklmnopqrstuvwxyz

$ ruby -e 'print *"a".."z"'
abcdefghijklmnopqrstuvwxyz

$ ruby -e 'print [*"a".."z"].join(" ")'
a b c d e f g h i j k l m n o p q r s t u v w x y z

# which gets you the full power of a language optimized for such domains
$ ruby -e 'puts *"a".."c"'
a
b
c

$ ruby -e 'puts ("a".."y").each_slice(5).map(&:join)'
abcde
fghij
klmno
pqrst
uvwxy

$ ruby -e 'puts ("x".."z").zip("a".."c").map(&:join)'
xa
yb
zc

$ ruby -e 'puts ("a".."c").map.with_index(1) { |c, n| "#{n}. #{c}" }'
1. a
2. b
3. c

@faho
Copy link
Member Author

faho commented Jun 7, 2020

Yeah, I ended up just adding a document. It's not currently referenced from the main documentation (just in the TOC) and it might need some sprucing up, but as a first pass I'm happy with it.

@faho faho modified the milestones: fish-future, fish 3.2.0 Jun 7, 2020
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Sep 5, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
docs An issue/PR that touches or should touch the docs enhancement
Projects
None yet
Development

No branches or pull requests

7 participants