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

Feature request: Support POSIX standard of using single hyphen "-" to mean standard input. #2432

Open
moh-hassan opened this issue May 27, 2024 · 5 comments

Comments

@moh-hassan
Copy link

Posix support of using single hyphen "-" to mean standard input.
ref: https://pubs.opengroup.org/onlinepubs/9699919799/

example

cd ~ && wget -O - "https://path/to/file" | tar xzf -

The- argument passed to tar after xzf means to read from standard input instead of from a named file.
The - argument passed to wget after -O means to write to standard output instead of to a named file.

Here OS will prompt the user to enter fileName from keyboard

It is nice if this feature is supported and system prompt the user to enter filename.

@elgonzo
Copy link
Contributor

elgonzo commented May 27, 2024

How exactly would you imagine this working / looking like in the source code? Considering that it is the application logic and not the System.CommandLine library code that is doing the reading/writing from/to some (named) file (or stream), how would you see System.CommandLine being able to exert influence on the application logic and make it read from stdin / write to stdout instead of a file without you needing to implement this stuff in the application logic anyway...?


It is nice if this feature is supported and system prompt the user to enter filename.

That's not what Posix stipulates. Posix establishes the hyphen operand as an (optional) convention to command reading from stdin / writing to stdout instead from/to a file, Posix does not define it to be a request for prompting for a file name.

@moh-hassan
Copy link
Author

moh-hassan commented May 28, 2024

That's not what Posix stipulates. Posix establishes the hyphen operand as an (optional) convention to command reading from stdin / writing to stdout instead from/to a file, Posix does not define it to be a request for prompting for a file name.

The section 12.1 Utility Argument Syntax

Guideline 13:
For utilities that use operands to represent files to be opened for either reading or writing, the '-' operand should be used to mean only standard input (or standard output when it is clear from context that an output file is being specified) or a file named -.

Note the term 'should be used' i.e it is not optional.

So, the single '-' operand is used to read a VALUE from STDIN (in my example of file name, it is a value from stdin that represent filename. it can be represent any value as i show in the examples below).

When using the command myutility -, the system will prompt the user to enter a value from the STDIN keyboard.
The - operand indicates that the input should come from standard input (stdin). User can then provide the necessary input interactively by typing it via the keyboard.

In case of STDIN is redirected like:
The command echo "data" | myutility -. myutility will receive the string "data" as its input through stdin.

In both cases the system is using STDIN and interpret the single dash as READ STDIN.

How exactly would you imagine this working / looking like in the source code

The parser is aware of the option and its value.
If the value EQUAL_TO '-' , prompt the user to enter value from stdin (in interactive keyboared) or input pipeline).
So the implementation of the single dash can be in the core of the library like the implementation of using @ for response file.

As POC, the parser is aware that single dash is a VALUE like:

myapp [diagram] project history --token - 

the parser output is:
[ myapp [ project [ history [ --token <-> ]  ] ] ]

Currently I implement this feature from within Incremental generator and hook the code to read from stdin in SetAction method.

Suggested Solution:
I think i can use the built-in CustomParser property to implement single-dash.
I will try it and feedback.

@KalleOlaviNiemitalo
Copy link

I have a few applications that read or write binary data (e.g. compressed formats) rather than text, and I want them to support - for reading from stdin or writing to stdout. In such cases:

  • If the user mistakenly specifies - as input when stdin is a terminal, the application should refuse to read binary data from there unless given some kind of --force option. Likewise for output. However, this should not be implicit validation in System.CommandLine because the command can have options that control whether the data format is text or binary. This validation should be implemented in the application.
  • I don't want System.CommandLine to pre-read stdin for the application, because the input may be very large and I'd rather have the application handle it in a streaming manner.
  • Any prompts or progress messages should go to stderr or /dev/tty, not to stdout, in order to keep stdout clean for piping to another application.

Other notes:

  • For input, argument validation should require an existing file or -.
  • It probably doesn't make sense to have - in multiple arguments of the same command, because it would be difficult to keep the streams separate in a pipe. This can be validated by the application.
  • CliArgument<FileInfo> feels like the wrong type to use because FileInfo doesn't have a method documented to return the original "-" string, although ToString() may do it in practice. So I'd rather use CliArgument<string> and open the file stream at the application side; that way, the application can control the file share mode etc. and has a string to display in any diagnostic messages.
  • I don't think - is useful to suggest in command completion, because it's only one character and it would clutter file name completion. (However, if System.CommandLine outputs command syntax information for shells to use, then it could be useful to include whether - is supported, in case a shell wants to use this for validating the command line and highlighting errors before the user runs the command.)

In the System.CommandLine API then, I think this would minimally be a validator that can be put in CliArgument<string> and CliOption<string>. One could also think about some metadata for shell integration but I haven't been keeping track of how that works on the Powderhouse branch.

@moh-hassan
Copy link
Author

I find that System.CommandLine already can support this feature without modification
by using CustomParser 👍
I tried the next tests to check single dash and all tests are passed

public class SinglDashTest
{

    [Fact]
    public void Argument_with_single_dash_can_read_from_stdin()
    {
        var argument = new CliArgument<string>("arg")
        {
            CustomParser = x => x.Tokens[0].Value == "-" ? readStdin() : x.Tokens[0].Value,
        };

        var result = new CliRootCommand { argument }.Parse("-");

        result.GetValue(argument)
            .Should()
            .Be("abc");
    }

    [Fact]
    public void Option_with_single_dash_can_read_from_stdin()
    {
        var argument = new CliOption<string>("--token")
        {
            CustomParser = x => x.Tokens[0].Value == "-" ? readStdin() : x.Tokens[0].Value,
        };

        var result = new CliRootCommand { argument }.Parse("--token -");

        result.GetValue(argument)
            .Should()
            .Be("abc");
    }

    string readStdin()
    {
      //show user a meaning prompt 
        Console.WriteLine("Enter Token");
        Console.SetIn(new StringReader("abc"));
        return Console.In.ReadToEnd();
    }
}

No need for new feature :)

@elgonzo
Copy link
Contributor

elgonzo commented May 28, 2024

Guideline 13:
For utilities that use operands to represent files to be opened for either reading or writing, the '-' operand should be used to mean only standard input (or standard output when it is clear from context that an output file is being specified) or a file named -.

Note the term 'should be used' i.e it is not optional.

Pay attention to the quoted guideline ending with "or a file named -." Posix does not require the single hyphen to mean a request to use stdin/stdout, it is left for the application developer to decide whether their app wants to treat the hyphen as a file name or a stdin/stdout redirect.

In case of STDIN is redirected like:
The command echo "data" | myutility -. myutility will receive the string "data" as its input through stdin.

That is an extremely simple use case. However, stdin/stdout redirects are not limited to simple short text values, data piped through stdin or stdout can encompass very large amounts of data that is not necessarily text. That was one of the motivations of my question of how you would imagine S:CL being involved/helpful in what is essentially the application's task to deal with. Anyway, since you found a solution for your use case, i consider my question answered :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants