1. 10
  1.  

  2. 5
    cat file.txt \    
      | sort           `# I *can* put a comment here` \
      | cut -f 1 \
        `# And I can put one here too` \
      | grep foo
    

    :^)

    1. 7

      I would usually just write:

        cat file.txt | # "useless cat" recapitulated
        sort         | # I *can* put a comment here
        cut -f 1     | # And I can put one here too
        grep foo       # and even here
      
      1. 6

        That’s OK for pipelines, but it falls down for the equivalent of

        ... find /bin               # traverse this directory
            -type f -a -executable  # filter executable files
            -a printf '%s %P\n'     # print size and path
          | sort -n                 # sort numerically
          ;
        

        The Tour has an example like this, probably should have put it in the blog post too …

        1. 2

          This screams to me a future accidental bug by not leading with the pipe and needless whitespace ceremony. It looks nice in a small example like this, but say you need to pipe that input into another command: if it’s a longer command, you’ll need to move all of the pipes and then possibly adjust all of the comments to the new whitespace if you’re on a char limit and then you may forget add back the pipe after grep because it’s easy to miss it on scan. And this doesn’t even considering that it’s not indented which is hard to parse visually.

          1. 1

            how would you do this without the useless cat?

            1. 2
              1. You can do: sort < file.txt | # comment ….
              2. UUoC makes sometimes sense and does not deserve so much hate as it gets in internet discussions.
              3. I prefer | + indentation on the beginning of the next line, so this style of comments is not much useful for me (If I have to, I will probably rather use the backtick trick).
              1. 2

                Also, just sort file.txt | ...

                1. 4

                  Or if you want to keep the order consistent with the data flow:

                  < file.txt \
                  sort | \
                  ...
                  
          2. 3

            I’ve seen this trick! But I don’t like all the noise with \ and backticks.

            I probably should have mentioned it … Right now it actually doesn’t work in OSH because # goes to the end of the line – we don’t look for a backtick. But that is not fundamental and could be changed. I haven’t seen it enough in real code to make it a priority. I think I saw it in some sandstorm shell scripts, and that’s about it.

            The 1.2M lines of shell corpus (https://www.oilshell.org/release/0.9.2/test/wild.wwz/) either contains 0 or 1 instances of it, I forget …

            1. 4

              But I don’t like all the noise with \ and backticks.

              i agree it’s a total hack. it wasn’t meant as a serious proposal (although i have used it in the past for a lack of alternatives), i was just being a smart-ass.

              oil’s approach looks way better :)

              1. 1

                Oh also another reason not to use that trick is that it actually relies on “empty elision”. Shell omits empty strings from argv, which is related to word splitting. Consider:

                $ argv X $(echo) `echo` Y
                

                This results in an argv of ['X', 'Y'] in shell, but ['X', '', '', 'Y'] in Oil. Compare with:

                $ argv X "$(echo)" "`echo`" Y
                

                I deem this too confusing which is why Oil Doesn’t Require Quoting Everywhere !

            2. 3

              as a side note, in python the textwrap.dedent function from the standard library is very useful for indenting multi line strings consistently with the surrounding code. (they still mess up my autoindent in vim, sadly).

              1. 3

                For bash/zsh, a fine way to write a command vertically is as an array:

                cmd=(
                    docker run # comment
                    # comment
                    --rm -it
                    -v "$PWD:$PWD:ro"
                    -w "$PWD"
                    -e "PYTHONPATH=$PWD/python"
                    "$IMG"
                    "${cmd[@]}"
                )
                "${cmd[@]}"
                

                Notes for those new to this:

                • For what I call a “command” (what doesn’t take a shell to execute), pipes are command delimiters – they go between commands, but can’t be part of them. You can have a pipe in an array, but only as an argument like any other.
                • Arrays arent’t a feature of POSIX shell. You can conclude what you want about that, but my take is that POSIX shell isn’t a “programming language” either, for missing this essential feature: Commands are arrays, and a language whose single purpose is to run commands, yet can’t represent them cleanly, isn’t (a programming language is supposed to be a useful abstraction). Furthermore, any good programming language would strive to make the correct thing to do easier than the wrong thing to do. For civilization’s sake, please forget about POSIX shell compatibility. At least until someone makes a POSIX compatible shell with arrays, but that currently is Bash.
                1. 2

                  Yes good point, although I find people have trouble with the “${cmd[@]}” syntax which is 8 extra chars. In Oil it’s:

                  const cmd = %(
                    docker run  # comment
                    # comment
                    $IMG  # no quotes needed
                  )
                  @cmd