trycmd icon indicating copy to clipboard operation
trycmd copied to clipboard

Piping from `echo` to provide standard input

Open jpmckinney opened this issue 3 years ago • 4 comments

I'd like to be able to show examples in my documentation that use standard input. My usual way to document this is something like:

$ echo "some simple input" | mycommand -
the output

... so that users can copy-paste it and get the same result (and then modify as needed). It would be great to be able to test that these examples work using trycmd.

Moved from https://github.com/assert-rs/trycmd/issues/168#issuecomment-1323763887

jpmckinney avatar Nov 22 '22 14:11 jpmckinney

As a variation of this, a heredoc is also a convenient option to explore:

$ my-tool --args <<END
[1, 2, 3]
END
[4, 5, 6]

They might be easier to implement because they don't require running arbitrary commands. (Then again, echo {single-argument} | could just get special treatment).

chrysn avatar Jun 13 '24 23:06 chrysn

A preliminary exploration comparing echo to the heredoc I suggested above indicates that echo is reasonably easy to handle on its own.

One aspect possibly worth discussing is the approach to evaluate the pipe; two variations come to mind -- fork out to processes or shim common commands

  1. Shimming common commands is an option. Given the issue has a few thumbs-up but no other use cases reported than echo, and that echo something | command-to-be-tested was also the thing I'd need, it stands to reason that "echo" could be a 20% effort solution that covers 80% of the cases. Some exploration of an echo-only processing has been explored in #344. A caveat about doing shell commands manually is that there is some risk of doing it wrong. This has notably happened when Debian deprecated which, users moved to command -v, which GNU Make tried to be smart about (post mortem of what that led to in a different project). With echo we can be relatively safe because POSIX is quite explicit about what is required and what is implementation defined behavior. Cases where something unimplemented is used could either produce an error (which is within what POSIX allows) or fall back to the previous behavior of echo X | command (which is to skip the test, at least with the setting I've tried) Apart from echo, something similar might be done for other shell mechanisms: heredoc (enabling newlines in input; popular with stuff in README.md) and input redirection from a file (for programs that don't have an argument that selects a different input than stdin; this is a bit more complex because it touches on the security implications of 2, albeit in an easier to handle way given we have the .in directories and open the file ourselves)
  2. Executing commands is an option. This appears to be the realm of #168 from which this was split out (therefore I assumed earlier that the option is ruled out for this issue). Discussion on whether this is compatible with the trust model of trycmd are probably better led over there. If all trust issues are resolved, there are still two variations:
    1. Do shell parsing here and set up the command under test to pipe the right way with the other programs. This is a rather complex undertaking (given there might be steps in there such as opening file descriptors exceeding stdin/out/err), but gives a lot of control over what is actually called.
    2. Delegate shell processing to a sh-compatible shell (/bin/sh). If the command under test relies on its argv[0] to be accurate, this may involve some prior rewriting of the command, or wrapping the command execution through another process.

With 1 being easy and attainable, and 2 providing a compatible extension, I'd like to suggest going route 1 now – it solves a practical issue, is not a 100% solution, but does not raise portability, security or complexity concerns.

chrysn avatar Jun 14 '24 14:06 chrysn

I like option 1.

Option 2 solves needs for which there seems to be no demand. Option 1 can be solved with only a little code as in the PR, so if demand for option 2 grows in the future, it can easily be replaced.

My goal in the readme is to provide simple examples that can be modified (eg replace the echo portion with other commands). The heredoc option (option 0) is not ideal as users of my CLI are typically doing many pipes through several commands; they are not expected to use heredocs themselves, so it might be confusing or misleading to use heredocs in the readme.

jpmckinney avatar Jun 14 '24 14:06 jpmckinney