Parser: fish fails to traverse pipes across newlines. #1285

Open
geoff-codes opened this Issue Feb 5, 2014 · 9 comments

Projects

None yet

5 participants

@geoff-codes
Contributor

I believe in any other shell that uses the pipeline syntax fish inherits, it is allowed to break the statement at the pipe itself. That is, if echo foo | cat - | cat is valid syntax, so is:

echo foo |
cat - |  # Tab space comments.
cat

foo

But in fish, the newline must be escaped:

Expected a command, but instead found end of the statement
echo foo |
          ^

Seems... buggish.

@zanchey
Member
zanchey commented Feb 5, 2014

Is there other syntax which can break across lines? Quoted strings can; brace expansion, redirection, command substitutions, and control statements can't.

@geoff-codes
Contributor

The other ones are the boolean operators.
These are VERY useful though, thanks for reminding me.

Can be used to order a non-branching logical secuence quite effectively.

#!/usr/bin/env sh
                                          cat "$0"; sleep 2; echo; echo

[ 1 -eq 0 ] && [ 0 -eq 1 ] && [ a = b ] && [ 1 -eq 10 ] && [ a = b ] &&
                                                          return 42  ||
                                           [ 0 -lt 10 ] && [ a = a ] &&
[ 2 -eq 2 ] && [ 1 -eq 1 ] && [ a = a ] &&


                       we=2 && too=to          #|/#/#*/|/##*
                  tea=to && test 2 != $we  ||#/####/
           echo we $we sit to have tea $tea | ##|
           cat  - |                     tee && #\
              echo now we $tea | cat - && #\ #\#\*##*>
                  echo $too who\? $too     we||:; echo>&2

Or you can write a fish haiku!

Same error in fish though, yep.

true; and
fish: Expected a command name, got token of type 'End of command'
true; and
         ^
@xfix
Member
xfix commented Feb 5, 2014

Boolean operators are pretty much functions with special parsing. Just write it like this instead, with new line instead of semicolon.

true
and false
@geoff-codes
Contributor

Oops. Right, duh. @zanchey darn you distracting me! Ha.

Correct me if I'm wrong x, but to be specific, they are (builtin) functions, which conditionally execute their arguments based of the return value of the prior statement.

... so anyway, just the issue in the title. Pipes.

@xfix
Member
xfix commented Feb 5, 2014

@g-nix: To be exact, those are keywords, not builtin functions. They are specificially parsed, so something like this works.

true
and begin
    echo Hello, world.
end

To be honest, I don't like how it works, but well, it's a keyword.

@geoff-codes
Contributor

... Interesting. It seems (from an analytic standpoint) it would work exactly the same as a function. But I'm sure implementation-wise its the way it is for some reason.

I can't see any logical reason why any function for which one or more argument is required, and further arguments are still needed, needs to be treated any differently than a block that has not seen its end statement. That is, to require not just whitespace to separate arguments, but literally to require code point 20 (or 8, tab), and allow multiple runs of these, but disallow a newline. Its all whitespace. For example,

if       #  if     \
  [      #     [   \
    x    #       a \
    =    #       = \
    x    #       a \
  ]      #     ]
  echo x #     echo a
end      #   end

is invalid on the left, but valid of the right. It's not like there's any ambiguity here — there's no possibility of it "getting it wrong" by completing the statement too soon. In each case if the correct number of arguments are not given, you get an error.

Also I just turned up another bug I think in testing that — while I can still command [ in the new parser, it tells me almost anywhere I put it on the command line, "unexpected end of string, square brackets do not match" if I call /bin/[, and if I disregard the syntax highlighting (red, straight through), "Unknown command '/bin/[ foo ]'.

@ridiculousfish
Member

We should consider the experience of novice users. I remember in bash I would often do something (like paste a string containing a backtick or other sigil) that would get me "lost" in a sequence of '>' prompts, where I had to know to ctrl-C out of it.

Good catch on the /bin/[ bug!

@geoff-codes
Contributor

@ridiculousfish no contention there — same thing happened to me — but I actually had an analogous experience with fish as well, something to this effect:

~> if true
       _   # < Um, where am I? What's going on here?
~> if true
       echo 1
       _   # < Ok I get it now.

The next time, I remember there's some type of automatic handling of interactive multiline statements, but I forgot that it's if [condition], not just if, and so I try to type something like

~> if
    true

and I get:

~> if
fish: Expected a command name, got token of type 'End of command'
if
  ^
~> 

and so I guess (maybe I'm just weird) I find (found) this to be a quite confusing distinction.

@ridiculousfish
Member

Thanks, cataloging those sort of experiences is quite useful.

@ridiculousfish ridiculousfish added this to the fish-future milestone Feb 10, 2014
@ridiculousfish ridiculousfish self-assigned this Apr 5, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment