|
| 1 | +`System.CommandLine` provides a set of default features for both people using it to develop apps and for the users of those apps. This is a quick overview of some of those features. |
| 2 | + |
| 3 | +# Suggestions |
| 4 | + |
| 5 | +Programs written using `System.CommandLine` have built-in support for tab completion. |
| 6 | + |
| 7 | + |
| 8 | + |
| 9 | +To enable it, the end user has to take a few steps once per shell, outlined [here](dotnet-suggest). Once this is done, completions will work for all apps written using `System.CommandLine`. |
| 10 | + |
| 11 | +# Help |
| 12 | + |
| 13 | +Command line applications typically have a way to get help, in order to understand the available options and their usage. |
| 14 | + |
| 15 | +```console |
| 16 | +> myapp -h |
| 17 | +Usage: |
| 18 | + myapp [options] |
| 19 | + |
| 20 | +Options: |
| 21 | + --int-option An option whose argument is parsed as an int |
| 22 | + --bool-option An option whose argument is parsed as a bool |
| 23 | + --file-option An option whose argument is parsed as a FileInfo |
| 24 | + --version Display version information |
| 25 | +``` |
| 26 | + |
| 27 | +Users might be accustomed to different prefixes in different ecosystems, especially if your app targets .NET Core and is used cross-platform, so apps built on `System.CommandLine` understand many different ways of requesting help. The following are all equivalent: |
| 28 | + |
| 29 | +```console |
| 30 | +> myapp -h |
| 31 | +> myapp /h |
| 32 | +> myapp --help |
| 33 | +> myapp -? |
| 34 | +> myapp /? |
| 35 | +``` |
| 36 | + |
| 37 | +# Version option |
| 38 | + |
| 39 | +Providing a way to check the version of your app is helpful to your users. |
| 40 | + |
| 41 | +`System.CommandLine` provides this by default. In the [help](Features-overview#Help) example you might have noticed an option, `--version`, that was not explicitly configured in the sample code. When you run your program with this option, you'll see something like this: |
| 42 | + |
| 43 | +```console |
| 44 | +> myapp --version |
| 45 | +1.0.0 |
| 46 | +``` |
| 47 | + |
| 48 | +# Parse preview |
| 49 | + |
| 50 | +Both users and developers often find it useful to see how an app will interpret a given input. One of the default features of a `System.CommandLine` app is the `[parse]` directive, which lets you preview a parse: |
| 51 | + |
| 52 | +```console |
| 53 | +> myapp [parse] --int-option not-an-int --file-option file.txt |
| 54 | +[ myapp ![ --int-option <not-an-int> ] [ --file-option <file.txt> ] *[ --bool-option <False> ] ] |
| 55 | +``` |
| 56 | + |
| 57 | +The `[parse]` directive tells the parser to parse the input and return a diagram of the result. Some things worth noting in the above example: |
| 58 | + |
| 59 | +* Commands (`myapp`), their child options, and the arguments to those options are grouped using square brackets. |
| 60 | +* For the option result `![ --int-option <not-an-int> ]`, the `!` indicates a parsing error. `not-an-int` could not be parsed to the expected type. |
| 61 | +* For the option result `*[ --bool-option <False> ]`, the `*` indicates that a value was not specified on the command line, so the parser's configured default was used. `False` is the effective value for this option. |
| 62 | + |
| 63 | +# Debugging |
| 64 | + |
| 65 | +When you're developing your app and you find that the parse preview isn't enough to explain something that's happening internally, the `[debug]` directive might help you. Set a breakpoint inside your code, prepend your command line input with `"[debug]"`, and hit `enter`: |
| 66 | + |
| 67 | +```console |
| 68 | +> myapp [debug] --file-option does-not-exist.txt |
| 69 | +Attach your debugger to process 14160 (myapp). |
| 70 | +``` |
| 71 | + |
| 72 | +Once you've attached your debugger to the specified process, execution will proceed to your breakpoint. |
| 73 | + |
| 74 | +# Response files |
| 75 | + |
| 76 | +Passing command line arguments via response files is helpful for very long command lines or for composing a command line from multiple sources. Here's an example: |
| 77 | + |
| 78 | +```console |
| 79 | +> myapp @c:\config\settings.rsp |
| 80 | +``` |
| 81 | + |
| 82 | +One or more response files can be specified in this way. Arguments and options are read from the file and expanded in-place as if they had been entered directly on the command line. |
| 83 | + |
| 84 | +# Adaptive rendering |
| 85 | + |
| 86 | +ANSI terminals support a variety of features by including ANSI escape sequences in standard input and output. These sequences can control the cursor, set text attributes and colors, and more. Windows [recently joined](https://blogs.msdn.microsoft.com/commandline/2018/06/27/windows-command-line-the-evolution-of-the-windows-command-line/) Linux and Mac in supporting these features. This is a capability of the new Windows Terminal and can be enabled programmatically in the Windows 10 Console. |
| 87 | + |
| 88 | +`System.Console.Rendering` adds support for detecting terminal settings and enabling the Window 10 Console's ANSI mode on demand. It also provides an API that can write output that looks correct based on those settings as well as when output is redirected, as is commonly the case on a build server or when your command line app is called by another command line app. |
| 89 | + |
| 90 | +The following are examples of output rendered by the same view code in these three different contexts. |
| 91 | + |
| 92 | +In PowerShell on Windows with ANSI mode enabled: |
| 93 | + |
| 94 | + |
| 95 | + |
| 96 | +In PowerShell with ANSI mode disabled: |
| 97 | + |
| 98 | + |
| 99 | + |
| 100 | +Redirected to a text file: |
| 101 | + |
| 102 | +``` |
| 103 | +Directory: C:\dev\command-line-api\build |
| 104 | +
|
| 105 | +Name Created Modified |
| 106 | +build.ps1 10/6/2018 10:56 AM 11/4/2018 7:10 PM |
| 107 | +build.sh 10/6/2018 10:56 AM 11/4/2018 7:10 PM |
| 108 | +cibuild.cmd 10/6/2018 10:56 AM 10/6/2018 10:56 AM |
| 109 | +cibuild.sh 10/6/2018 10:56 AM 10/6/2018 10:56 AM |
| 110 | +NuGet.props 10/6/2018 10:56 AM 10/6/2018 10:56 AM |
| 111 | +SignToolData.json 10/6/2018 10:56 AM 11/19/2018 1:56 PM |
| 112 | +Toolset.proj 10/6/2018 10:56 AM 10/6/2018 10:56 AM |
| 113 | +Versions.props 10/6/2018 10:56 AM 11/19/2018 1:56 PM |
| 114 | +
|
| 115 | +``` |
| 116 | + |
| 117 | +The raw text written to standard out in the first example is this: |
| 118 | + |
| 119 | +```console |
| 120 | +\u001b[1;1H\u001b[39m\u001b[49m\u001b[2;1HDirectory: \u001b[38;2;235;30;180mC:\dev\command-line-api\build\u001b[39m\u001b[39m\u001b[49m\u001b[3;1H\u001b[39m\u001b[49m\u001b[4;1H\u001b[4mName\u001b[24m\u001b[39m\u001b[49m \u001b[4;20H\u001b[4mCreated\u001b[24m\u001b[39m\u001b[49m \u001b[4;40H\u001b[4mModified\u001b[24m\u001b[39m\u001b[49m \u001b[5;1H\u001b[37mbuild.ps1\u001b[39m\u001b[39m\u001b[49m \u001b[5;20H10/6/2018 \u001b[90m10:56 AM\u001b[39m\u001b[49m \u001b[5;40H11/4/2018 \u001b[90m7:10 PM\u001b[39m\u001b[49m \u001b[6;1H\u001b[37mbuild.sh\u001b[39m\u001b[39m\u001b[49m \u001b[6;20H10/6/2018 \u001b[90m10:56 AM\u001b[39m\u001b[49m \u001b[6;40H11/4/2018 \u001b[90m7:10 PM\u001b[39m\u001b[49m \u001b[7;1H\u001b[37mcibuild.cmd\u001b[39m\u001b[39m\u001b[49m \u001b[7;20H10/6/2018 \u001b[90m10:56 AM\u001b[39m\u001b[49m \u001b[7;40H10/6/2018 \u001b[90m10:56 AM\u001b[39m\u001b[49m\u001b[8;1H\u001b[37mcibuild.sh\u001b[39m\u001b[39m\u001b[49m \u001b[8;20H10/6/2018 \u001b[90m10:56 AM\u001b[39m\u001b[49m \u001b[8;40H10/6/2018 \u001b[90m10:56 AM\u001b[39m\u001b[49m\u001b[9;1H\u001b[37mNuGet.props\u001b[39m\u001b[39m\u001b[49m \u001b[9;20H10/6/2018 \u001b[90m10:56 AM\u001b[39m\u001b[49m \u001b[9;40H10/6/2018 \u001b[90m10:56 AM\u001b[39m\u001b[49m\u001b[10;1H\u001b[37mSignToolData.json\u001b[39m\u001b[39m\u001b[49m \u001b[10;20H10/6/2018 \u001b[90m10:56 AM\u001b[39m\u001b[49m \u001b[10;40H11/19/2018 \u001b[90m1:56 PM\u001b[39m\u001b[49m\u001b[11;1H\u001b[37mToolset.proj\u001b[39m\u001b[39m\u001b[49m \u001b[11;20H10/6/2018 \u001b[90m10:56 AM\u001b[39m\u001b[49m \u001b[11;40H10/6/2018 \u001b[90m10:56 AM\u001b[39m\u001b[49m\u001b[12;1H\u001b[37mVersions.props\u001b[39m\u001b[39m\u001b[49m \u001b[12;20H10/6/2018 \u001b[90m10:56 AM\u001b[39m\u001b[49m \u001b[12;40H11/19/2018 \u001b[90m1:56 PM\u001b[39m\u001b[49m |
| 121 | + |
| 122 | +``` |
| 123 | + |
| 124 | + In ANSI mode, the Windows Console interprets these escape sequences into cursor movements and colors. As you can see in the first example above, ANSI mode enables the display of RGB colors and underlining that are not supported otherwise on Windows. Most Linux and macOS terminals as well as the Windows Terminal support this form of rendering by default. |
| 125 | + |
| 126 | + The examples above build the table structure by positioning the cursor for each cell and then writing the content. In an ANSI-capable terminal, this is done using ANSI escape sequences such as `\u001b[1;1H`. The equivalent `System.Console` call, which is needed in non-ANSI terminals, looks like this: `Console.SetCursorPosition(0, 0)`. Meanwhile, the third example renders the layout using spaces and newlines, since there is no cursor when output is redirected. |
| 127 | + |
| 128 | + Providing a common API across these very different modes so that you don't have to write the code three times is a major goal of `System.CommandLine.Rendering`. The API is still very rough but you can explore these capabilities in the `RenderingPlayground` [sample](https://github.com/dotnet/command-line-api/tree/master/samples/RenderingPlayground). |
| 129 | + |
| 130 | + ## Rendering directives |
| 131 | + |
| 132 | +Output modes can also be specified directly. If you know that you want a specific form of output, you can bypass the mode detection of `System.CommandLine.Rendering` and use a [directive](Syntax-Concepts-and-Parser#directives). |
| 133 | + |
| 134 | +The following example will output ANSI to a text file. |
| 135 | + |
| 136 | +```console |
| 137 | +> .\RenderingPlayground.exe [output:ansi] --sample dir > sample.txt |
| 138 | +``` |
| 139 | + |
| 140 | +(The parameter for the output directive is case-insensitive.) |
| 141 | + |
| 142 | +The supported output modes are: |
| 143 | + |
| 144 | +* `Ansi`: Output is rendered using ANSI escape sequences. In-place re-rendering is supported. |
| 145 | +* `NonAnsi`: Output is rendered using `System.Console` cursor positioning. In-place re-rendering is supported. |
| 146 | +* `PlainText`: Output is rendered with additional whitespace so that, for example, if redirected to a text file, the layout will look correct. In-place re-rendering is not supported. |
0 commit comments