Skip to content

Commit fe87561

Browse files
committed
Extract code snippets
Use extracted code snippets instead of inline code.
1 parent d5e450a commit fe87561

File tree

2 files changed

+36
-79
lines changed

2 files changed

+36
-79
lines changed

docs/csharp/fundamentals/tutorials/file-based-programs.md

Lines changed: 11 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -152,19 +152,15 @@ If you prefer, you can remove the extension so you can type `./AsciiArt` instead
152152

153153
Next, add a package that supports ASCII art, [Colorful.Console](https://www.nuget.org/packages/Colorful.Console). To add a package to a file based program, you use the `#:package` directive. Add the following directive after the `#!` directive in your AsciiArt.cs file:
154154

155-
```csharp
156-
157-
```
155+
:::code language="csharp" source="./snippets/file-based-programs/AsciiArt.cs" id="ColorfulPackage":::
158156

159157
> [!IMPORTANT]
160158
>
161159
> The version `1.2.15` was the latest version when this tutorial was last updated. If there's a newer version available, use the latest version to ensure you have the latest security packages.
162160
163161
Next, change the lines that call `Console.WriteLine` to use the `Colorful.Console.WriteAscii` method instead:
164162

165-
```csharp
166-
Colorful.Console.WriteAscii(message);
167-
```
163+
:::code language="csharp" source="./snippets/file-based-programs/AsciiArt.cs" id="WriteAscii":::
168164

169165
Run the program, and you see ASCII art output instead of echoed text. Next, let's add command line parsing. The current version writes each word as a different line of output. The command line arguments you add support two features:
170166

@@ -193,110 +189,48 @@ The `System.CommandLine` library offers several key benefits:
193189

194190
To add command line parsing capabilities, first add the `System.CommandLine` package. Add this directive after the existing package directive:
195191

196-
```csharp
197-
198-
```
192+
:::code language="csharp" source="./snippets/file-based-programs/AsciiArt.cs" id="CommandLinePackage":::
199193

200194
> [!IMPORTANT]
201195
>
202196
> The version `2.0.0-beta6` was the latest version when this tutorial was last updated. If there's a newer version available, use the latest version to ensure you have the latest security packages.
203197
204198
Next, add the necessary using statements at the top of your file (after the `#!` and `#:package` directives):
205199

206-
```csharp
207-
using System.CommandLine;
208-
using System.CommandLine.Parsing;
209-
```
200+
:::code language="csharp" source="./snippets/file-based-programs/AsciiArt.cs" id="Usings":::
210201

211202
Define the delay option and messages argument. In command-line applications, options typically begin with `--` (double dash) and can accept arguments. The `--delay` option accepts an integer argument that specifies the delay in milliseconds. The `messagesArgument` defines how any remaining tokens after options are parsed as text. Each token becomes a separate string in the array, but text can be quoted to include multiple words in one token. For example, `"This is one message"` becomes a single token, while `This is four tokens` becomes four separate tokens. Add the following code to create the <xref:System.CommandLine.Option`1?displayProperty=nameWithType> and <xref:System.CommandLine.Argument`1?displayProperty=nameWithType> objects to represent the command line option and argument:
212203

213-
```csharp
214-
Option<int> delayOption = new("--delay")
215-
{
216-
Description = "Delay between lines, specified as milliseconds.",
217-
DefaultValueFactory = parseResult => 100
218-
};
219-
220-
Argument<string[]> messagesArgument = new("Messages")
221-
{
222-
Description = "Text to render."
223-
};
224-
```
204+
:::code language="csharp" source="./snippets/file-based-programs/AsciiArt.cs" id="OptionArgument":::
225205

226206
The preceding code defines the argument type for the `--delay` option, and that the arguments are an array of `string` values. This application has only one command, so you use the *root command*. Create a root command and configure it with the option and argument. Add the argument and option to the root command:
227207

228-
```csharp
229-
RootCommand rootCommand = new("Ascii Art file-based program sample");
208+
:::code language="csharp" source="./snippets/file-based-programs/AsciiArt.cs" id="RootCommand":::
230209

231-
rootCommand.Options.Add(delayOption);
232-
rootCommand.Arguments.Add(messagesArgument);
233-
```
234210

235211
Next, add the code to parse the command line arguments and handle any errors. This code validates the command line arguments and stores parsed arguments in the <xref:System.CommandLine.ParseResult?displayProperty=nameWithType> object:
236212

237-
```csharp
238-
ParseResult result = rootCommand.Parse(args);
239-
foreach (ParseError parseError in result.Errors)
240-
{
241-
Console.Error.WriteLine(parseError.Message);
242-
}
243-
if (result.Errors.Count > 0)
244-
{
245-
return 1;
246-
}
247-
```
213+
:::code language="csharp" source="./snippets/file-based-programs/AsciiArt.cs" id="ParseAndValidate":::
248214

249215
The preceding code validates all command line arguments. If the validation fails, errors are written to the console, and the app exits.
250216

251217
## Use parsed command line results
252218

253219
Now, finish the app to use the parsed options and write the output. First, define a record to hold the parsed options. File-based apps can include type declarations, like records. They must be after all top-level statements and local functions. Add a `record` declaration to store the messages and the delay option value:
254220

255-
```csharp
256-
public record AsciiMessageOptions(string[] Messages, int Delay);
257-
```
221+
:::code language="csharp" source="./snippets/file-based-programs/AsciiArt.cs" id="Record":::
258222

259223
Now that you declared the record to store those results, add a local function to process the parse results and store the values in an instance of the record. Add the following local function before the record declaration. This method handles both command line arguments and standard input, and returns a new record instance:
260224

261-
```csharp
262-
async Task<AsciiMessageOptions> ProcessParseResults(ParseResult result)
263-
{
264-
int delay = result.GetValue(delayOption);
265-
List<string> messages = [.. result.GetValue(messagesArgument) ?? Array.Empty<string>()];
266-
267-
if (messages.Count == 0)
268-
{
269-
while (Console.ReadLine() is string line && line.Length > 0)
270-
{
271-
Colorful.Console.WriteAscii(line);
272-
await Task.Delay(delay);
273-
}
274-
}
275-
return new ([..messages], delay);
276-
}
277-
```
225+
:::code language="csharp" source="./snippets/file-based-programs/AsciiArt.cs" id="ProcessParsedArgs":::
278226

279227
Next, create a local function to write the ASCII art with the specified delay. This function writes each message in the record with the specified delay between each message:
280228

281-
```csharp
282-
async Task WriteAsciiArt(AsciiMessageOptions options)
283-
{
284-
foreach(string message in options.Messages)
285-
{
286-
Colorful.Console.WriteAscii(message);
287-
await Task.Delay(options.Delay);
288-
}
289-
}
290-
```
229+
:::code language="csharp" source="./snippets/file-based-programs/AsciiArt.cs" id="WriteAscii":::
291230

292231
Finally, replace the `if` clause you wrote earlier with the following code to process the command line arguments and write the output:
293232

294-
```csharp
295-
var parsedArgs = await ProcessParseResults(result);
296-
297-
await WriteAsciiArt(parsedArgs);
298-
return 0;
299-
```
233+
:::code language="csharp" source="./snippets/file-based-programs/AsciiArt.cs" id="InvokeCommand":::
300234

301235
## Test the final application
302236

docs/csharp/fundamentals/tutorials/snippets/file-based-programs/AsciiArt.cs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,18 @@
11
#!/usr/local/share/dotnet/dotnet run
22

3+
// <ColorfulPackage>
34
#:package Colorful.Console@1.2.15
5+
// </ColorfulPackage>
6+
// <CommandLinePackage>
47
#:package System.CommandLine@2.0.0-beta6
8+
// </CommandLinePackage>
59

10+
// <Usings>
611
using System.CommandLine;
712
using System.CommandLine.Parsing;
13+
// </Usings>
814

15+
// <OptionArgument>
916
Option<int> delayOption = new("--delay")
1017
{
1118
Description = "Delay between lines, specified as milliseconds.",
@@ -16,11 +23,16 @@
1623
{
1724
Description = "Text to render."
1825
};
26+
// </OptionArgument>
1927

28+
// <RootCommand>
2029
RootCommand rootCommand = new("Ascii Art file-based program sample");
2130

2231
rootCommand.Options.Add(delayOption);
2332
rootCommand.Arguments.Add(messagesArgument);
33+
// </RootCommand>
34+
35+
// <ParseAndValidate>
2436
ParseResult result = rootCommand.Parse(args);
2537
foreach (ParseError parseError in result.Errors)
2638
{
@@ -30,12 +42,16 @@
3042
{
3143
return 1;
3244
}
45+
// </ParseAndValidate>
3346

47+
// <InvokeCommand>
3448
var parsedArgs = await ProcessParseResults(result);
3549

3650
await WriteAsciiArt(parsedArgs);
3751
return 0;
52+
// </InvokeCommand>
3853

54+
// <ProcessParsedArgs>
3955
async Task<AsciiMessageOptions> ProcessParseResults(ParseResult result)
4056
{
4157
int delay = result.GetValue(delayOption);
@@ -45,20 +61,27 @@ async Task<AsciiMessageOptions> ProcessParseResults(ParseResult result)
4561
{
4662
while (Console.ReadLine() is string line && line.Length > 0)
4763
{
64+
// <WriteAscii>
4865
Colorful.Console.WriteAscii(line);
66+
// </WriteAscii>
4967
await Task.Delay(delay);
5068
}
5169
}
52-
return new ([..messages], delay);
70+
return new([.. messages], delay);
5371
}
72+
// </ProcessParsedArgs>
5473

74+
// <WriteAscii>
5575
async Task WriteAsciiArt(AsciiMessageOptions options)
5676
{
57-
foreach(string message in options.Messages)
77+
foreach (string message in options.Messages)
5878
{
5979
Colorful.Console.WriteAscii(message);
6080
await Task.Delay(options.Delay);
6181
}
6282
}
83+
// </WriteAscii>
6384

85+
// <Record>
6486
public record AsciiMessageOptions(string[] Messages, int Delay);
87+
// </Record>

0 commit comments

Comments
 (0)