Hacker News new | ask | show | jobs
by heleninboodler 1101 days ago
Am I the only one completely confused by the examples that appear to put command line arguments after shell end-of-line comments? Is that not a typical shell?

example:

  nix run .#cowsay -- flakes are neat
Some explanation of what the heck this means would be really useful.
5 comments

yikes! thanks for pointing that out. The blog's renderer is confused too and renders the `#cowsay -- flakes are neat` as a comment.

To explain what's happening:

- The example above is running `nix run <flake output attribute> -- <arguments to pass to the flake output's binary>`.

- The `<flake output attribute>` here is `.#cowsay`, which is to be read as: `<flake reference>#<attribute path>`. The # is a separator here.

- The `<flake reference>` being `.` implies its a local flake at the current directory. The `<attribute path>` in this case is the output from the flake i.e. the `cowsay` program.

further fun to be found at: https://nixos.org/manual/nix/stable/command-ref/new-cli/nix....

As a meta-comment, yeah, this is kinda non-trivial for most of us. This is why we build devbox which provides a more familiar UX like `devbox add cowsay && devbox run -- cowsay "flakes are neat"`

"--" isn't anything special in a typical shell. It's just another argument, one that customarily means "pass the rest of arguments on to a subprocess". Or are you confused about the "#"? It doesn't start a comment in the middle of a token.
> one that customarily means "pass the rest of arguments on to a subprocess".

It's convenient for passing options and args to a subprocess, but it customarily means "don't interpret anything following this as a short or long option, just as a positional argument". For example:

  touch -f     # error
  touch -- -f  # creates a file named "-f"
  rm *         # oh crap we just passed "rm -f" a bunch of files
  rm -- *      # don't treat that "-f" as an option, just delete the file named "-f"
It was the "#". I didn't realize that about the behavior in the middle of a token, and apparently the syntax colorizer doesn't either.
https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1...

The first -- argument that is not an option-argument should be accepted as a delimiter indicating the end of options. Any following arguments should be treated as operands, even if they begin with the '-' character.

The comment syntax for most (virtually all?) shells actually doesn't start with a pound sign but with the word boundary or whitespace preceding the pound sign. You can have unescaped pound signs within tokens in shell languages, and thus they are used (perhaps unfortunately) as delimiters in the current flake URI schema.
It's nix run, the dot means current directory, # means flake, cowsay is the attribute, and then anything after -- is passed to what's run by that command, which is typical of many Unix programs.

So it's run the cowsay attribute from the flake in the current directory, passing flakes are neat as input to cowsay.