Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(487)

Side by Side Diff: src/site/docs/tutorials/cmdline/index.markdown

Issue 116673004: adding new command-line app tutorial (Closed) Base URL: https://github.com/dart-lang/dartlang.org.git@master
Patch Set: mods based on Kathy's feedback Created 6 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 ---
2 layout: default
3 title: "Write Command-Line Apps"
4 description: "Basics for command-line apps"
5 has-permalinks: true
6 tutorial:
7 id: dart-io
8 next: fetchdata/
9 next-title: "Fetch Data Dynamically"
10 prev: futures/
11 prev-title: "Use Future-Based APIs"
12 ---
13
14 {% capture whats_the_point %}
sethladd 2014/01/03 00:57:28 Global: I'd like to see some advice for when to us
sethladd 2014/01/03 00:57:28 Global: I couldn't find it, can you link to the pr
mem 2014/01/03 17:38:02 Done.
mem 2014/01/03 17:38:02 There's only one place where synchronous is used a
15
16 * Server-side applications need to do input and output.
sethladd 2014/01/03 00:57:28 the tutorial says "command-line" but here you say
mem 2014/01/03 17:38:02 Done.
17 * The dart:io library provides I/O functionality.
18 * The args package helps define and parse command-line arguments.
19 * Most input and output requires the use of Streams.
20 * Streams provide a series of asynchronous data events.
21 * To handle asynchronous data, you need to use Futures.
22
23 {% endcapture %}
24
25 {% capture sample_links %}
26
27 <p> This tutorial features these examples:</p>
28 * helloworld42
29 * dcat
30 * dgrep
31
32 <p>
33 Don't have the source code?
sethladd 2014/01/03 00:57:28 the source for the examples above?
mem 2014/01/03 17:38:02 this is consistent with all of the other tutorials
34 <a href="https://github.com/dart-lang/dart-tutorials-samples/archive/master.zip" >
35 Download it.
36 </a>
37
38 {% endcapture %}
39
40 {% capture content %}
41
42 <div class="tute-target-title">
43 <h1>{{page.title}}</h1>
44 <h3>An introduction to standalone apps</h3>
sethladd 2014/01/03 00:57:28 and here we use standalone (instead of command-lin
mem 2014/01/03 17:38:02 we use standalone here otherwise we use the exact
45 </div>
46
47 <div id="under-construction" markdown="1">
48 <h3> <i class="icon-wrench"> </i> Under construction </h3>
49
50 This is a draft under construction.
51 Your kindly worded
52 <a
53 href="http://code.google.com/p/dart/issues/entry?template=Tutorial%20feedback"
54 target="_blank">
55 comments and suggestions
56 </a>
57 are appreciated.
58 Thank you for your patience.
59 </div>
60
61 This tutorial looks at a few small command-line applications.
sethladd 2014/01/03 00:57:28 opinion: this tutorial teaches you how to build co
mem 2014/01/03 17:38:02 Done.
62 These programs use resources that most command-line applications need,
63 including the standard output, error, and input streams,
64 command-line arguments, files and directories, and more.
65
66 * [Run an app with the standalone Dart VM](#run-the-first-app)
67 * [Check out the dcat example](#dcat-code)
68 * [Parsing command-line arguments](#cmd-line-args)
69 * [Reading and writing with stdin, stdout, and stderr](#std-in-out-err)
70 * [Getting info about a file](#filesystementity)
71 * [Reading a file](#reading-a-file)
72 * [Writing a file](#writing-a-file)
73 * [Getting environment information](#env-var)
74 * [Setting exit codes](#exit-codes)
75 * [Check out the code for another example](#dgrep-code)
76 * [Summary](#summary)
77 * [Other resources](#other-resources)
78 * [What next?](#what-next)
79
80 ## Run an app with the standalone Dart VM {#run-the-first-app}
sethladd 2014/01/03 00:57:28 other headers are "-ing" like "reading" or "writin
mem 2014/01/03 17:38:02 Done.
81
82 To run a command-line app, you need the Dart VM (`dart`),
83 which comes with the Dart Editor (in the Dart download)
sethladd 2014/01/03 00:57:28 use a link for "Dart download" ?
mem 2014/01/03 17:38:02 Done.
84 or in the [Dart SDK](/tools/sdk/) download.
85 If you install the Dart download in a directory called `~/myDartDownload`,
86 you can find `dart`
87 in `~/myDartDownload/dart-sdk/bin`.
88
89 <div markdown="1">
90
91 ![The path to the Dart VM](images/filestructure.png)
92
93 </div>
94
95 By putting this directory in your PATH
96 you can refer to the `dart` command and other commands,
97 such as the dart analyzer, by name.
98
99 Let's run a small program.
100
101 <ol>
102 <li markdown="1">
103 Create a file called `helloworld42.dart` that contains this code:
104
105 {% prettify dart %}
106 void main() {
107 int fortyTwo = 'Hello, World'; // Type mismatch.
sethladd 2014/01/03 00:57:28 I think teaching the optional types here, and how
mem 2014/01/03 17:38:02 Done.
108 print(fortyTwo);
109 }
110 {% endprettify %}
111 </li>
112
113 <li markdown="1">
114 In the directory that contains the file you just created,
115 run the program with the command as shown by the highlighted text.
116
117 {% prettify bash %}
118 % [[highlight]]dart helloworld42.dart[[/highlight]]
119 Hello, World!
120 %
121 {% endprettify %}
122
123 The program runs cleanly in spite
124 of the type mismatch in the source code.
125 Types are optional in Dart and by default the Dart VM
126 does not do type-checking.
127 </li>
128
129 <li markdown="1">
130 Run the `helloworld42.dart` program using the `--checked` flag:
131
132 {% prettify bash %}
133 % [[highlight]]dart --checked helloworld42.dart[[/highlight]]
134 Unhandled exception:
135 type 'String' is not a subtype of type 'int' of 'fortyTwo'.
136 ...
137 %
138 {% endprettify %}
139
140 The program fails because the program assigns a string to an integer.
141
142 The `--checked` option enables
143 assertion and type checks (checked mode).
144 Checked mode is useful during development for finding errors
145 related to types and for testing `assert` statements.
146 We recommend running your programs in checked mode during prototyping
147 and development, and turning it off for production.
148
149 Note that the flags and options passed to the Dart VM go before the name
150 of the Dart file to run.
151 </li>
152 </ol>
153
154 ## Check out the dcat example {#dcat-code}
sethladd 2014/01/03 00:57:28 Can you make it more clear that you'll go into mor
mem 2014/01/03 17:38:02 Done.
155
156 Take a quick look at the code for a small sample called `dcat`,
157 which is a simplified implementation of the Unix cat utility.
sethladd 2014/01/03 00:57:28 explain what the Unix cat utility is. 80% of our u
mem 2014/01/03 17:38:02 Done.
158 This program uses various classes, functions, and properties
159 available to command-line apps.
160 Hover over the highlighted code below for explanations.
161
162 <pre class="prettyprint lang-dart">
163 import 'dart:async';
164 import 'dart:convert';
165 import 'dart:io';
166
167 import 'package:args/args.dart';
168
169 const LINE_NUMBER = 'line-number';
170 var NEWLINE = '\n';
171
172 ArgResults argResults;
173
174 void main(<a href="#" class="dart-popover" data-toggle="popover" title="Command- line arguments" data-html="true" data-trigger="hover focus" data-content="Comman d-line arguments are passed in by the system when the program starts.">List&lt;S tring&gt; arguments</a>) {
175 exitCode = 0; // Presume success.
sethladd 2014/01/03 00:57:28 I'm left wondering where exitCode came from?
mem 2014/01/03 17:38:02 Done.
176 final parser = new ArgParser()
177 ..addFlag(LINE_NUMBER, negatable: false, abbr: 'n');
178
179 <a href="#" class="dart-popover" data-toggle="popover" title="Arguments parser " data-html="true" data-trigger="hover focus" data-content="The ArgParser class provides help with parsing command-line arguments.">argResults = parser.parse(ar guments);</a>
180 List&lt;String&gt; paths = argResults.rest;
181
182 dcat(paths, argResults[LINE_NUMBER]);
183 }
184
185 Future dcat(List&lt;String&gt; paths, bool showLineNumbers) {
186 if (paths.isEmpty) {
187 // No files provided as arguments. Read from stdin and print each line.
188 return <a href="#" class="dart-popover" data-toggle="popover" title="Standar d I/O streams" data-html="true" data-trigger="hover focus" data-content="This co de reads from the standard input stream and pipes the data to the standard outpu t stream.">stdin.pipe(stdout);</a>
189 } else {
190 return Future.forEach(paths, (path) {
191 int lineNumber = 1;
192 <a href="#" class="dart-popover" data-toggle="popover" title="Open a file for reading" data-html="true" data-trigger="hover focus" data-content="Use the F ile class to represent a file on the native file system.">Stream&lt;List&lt;int& gt;&gt; stream = new File(path).openRead();</a>
193 return stream
194 <a href="#" class="dart-popover" data-toggle="popover" title="Data con verters" data-html="true" data-trigger="hover focus" data-content="Convert data as it becomes available on a stream.">.transform(UTF8.decoder)</a>
195 .transform(const LineSplitter())
196 <a href="#" class="dart-popover" data-toggle="popover" title="Get data from a stream" data-html="true" data-trigger="hover focus" data-content="Listen to a stream to get data when it becomes available.">.listen((line)</a> {
197 if (showLineNumbers) {
198 stdout.write('${lineNumber++} ');
199 }
200 stdout.writeln(line);
201 }).asFuture().catchError((_) =&gt; _handleError(path));
202 });
203 }
204 }
205
206 _handleError(String path) {
207 <a href="#" class="dart-popover" data-toggle="popover" title="Test a path" dat a-html="true" data-trigger="hover focus" data-content="You can get information a bout the file system on which your program is running.">FileSystemEntity.isDirec tory(path)</a>.then((isDir) {
208 if (isDir) {
209 print('error: $path is a directory');
210 } else {
211 print('error: $path not found');
212 }
213 });
214 <a href="#" class="dart-popover" data-toggle="popover" title="Exit code" data- html="true" data-trigger="hover focus" data-content="A well-behaved command-line app sets an exit code to indicate whether the program was successful.">exitCode = 2;</a>
215 }
216
217 </pre>
218
219 ## Parsing command-line arguments {#cmd-line-args}
220
221 The
222 <a href="https://api.dartlang.org/args.html" target="_blank">args</a>
223 package provides
sethladd 2014/01/03 00:57:28 Are they going to know what a package is?
mem 2014/01/03 17:38:02 Done.
224 parser support for transforming raw command-line arguments
225 into a set of options, flags, and additional values.
226 Import the library as follows:
227
228 {% prettify dart %}
229 import 'package:args/args.dart';
230 {% endprettify %}
231
232 The args library contains two classes:
233
234 | Library | Description |
235 |---|---|
236 | <a href="https://api.dartlang.org/args/ArgParser" target="_blank">ArgParser</a > | A class that parses command-line arguments |
237 | <a href="https://api.dartlang.org/args/ArgResults" target="_blank">ArgResults< /a> | The result of parsing command-line arguments using ArgParser. |
238 {: .table }
239
240 Let's take a look at the `dcat` sample,
241 which uses ArgParser and ArgResults to parse and store its command-line argument s.
242
243 <ol>
244 <li markdown="1">
245 Copy the sample file from the github repo:
246 <a href="https://github.com/dart-lang/dart-tutorials-samples/blob/master/bin/dca t.dart">dcat.dart</a>.
247 </li>
248
249 <li markdown="1">
250 Run the program from the command line as shown by the highlighted text.
251
252 {% prettify bash %}
253 $ [[highlight]]dart dcat.dart -n quotes.txt[[/highlight]]
254 1 Be yourself. Everyone else is taken. -Oscar Wilde
255 2 Don't cry because it's over, smile because it happened. -Dr. Seuss
256 3 You only live once, but if you do it right, once is enough. -Mae West
257 ...
258 {% endprettify %}
259
260 The program displays the contents of the source code file and
261 preceeds each line with a line number.
262 </li>
263
264 </ol>
265
266 The following diagram shows how the `dcat` command line used above
267 is parsed into the `ArgResults` object.
268
269 ![ArgsParser parses command-line arguments](images/commandlineargs.png)
270
271 You can access flags and options by name,
272 treating the ArgResults object like a Map.
273 You can access other values with properties such as `rest`.
274
275 Here's the code from `dcat` that deals with command-line arguments:
276
277 <pre class="prettyprint lang-dart">
278
279 ...
280 <a href="#" class="dart-popover" data-toggle="popover" title="Parsed arguments" data-html="true" data-trigger="hover focus" data-content="This object contains p arsed options and flags.">ArgResults argResults;</a>
281
282 void main(<a href="#" class="dart-popover" data-toggle="popover" title="Command- line arguments" data-html="true" data-trigger="hover focus" data-content="The sy stem passes command-line arguments into the program in a list of strings.">List& lt;String&gt; arguments</a>) {
283 final parser = new ArgParser()
284 <a href="#" class="dart-popover" data-toggle="popover" title="Define a val id flag" data-html="true" data-trigger="hover focus" data-content="Add a flag de finition to the command-line argument parser. This code defines the flag -n, whi ch when used displays line numbers.">..addFlag(LINE_NUMBER, negatable: false, ab br: 'n')</a>;
285
286 argResults = parser.<a href="#" class="dart-popover" data-toggle="popover" tit le="Parse the arguments" data-html="true" data-trigger="hover focus" data-conten t="Parse the arguments that were passed into the main() function. The parser sto ps parsing if it finds an undefined option or flag.">parse(arguments)</a>;
287 List&lt;String&gt; paths = <a href="#" class="dart-popover" data-toggle="popov er" title="Remaining arguments" data-html="true" data-trigger="hover focus" data -content="To get the arguments that remain after parsing all of the valid option s and flags, use the rest property.">argResults.rest</a>;
288
289 dcat(paths, <a href="#" class="dart-popover" data-toggle="popover" title="Refe r to options and flags by name" data-html="true" data-trigger="hover focus" data -content="You can refer to an option or flag by name treating the ArgResults obj ect like a Map.">argResults[LINE_NUMBER])</a>;
290 }
291 ...
292 </pre>
293
294 The
295 <a href="https://api.dartlang.org/args.html" target="_blank">API docs</a>
296 for the args library
297 provide detailed information
298 to help you use ArgsParser and ArgResults classes.
299
300 ## Reading and writing with stdin, stdout, and stderr {#std-in-out-err}
301
302 Like other languages,
303 Dart has standard output, standard error, and standard input streams.
304 The standard I/O streams are defined at the top level of the dart:io library,
305 which you import as follows:
306
307 {% prettify dart %}
308 import 'dart:io';
309 {% endprettify %}
310
311 Only command-line applications, not web applications,
312 can use the dart:io library.
313
314 Standard output and standard error are
315 <a href="https://api.dartlang.org/dart_io/IOSink.html" target="_blank">IOSink</a >s
316 rather than streams, but can be bound to a stream.
sethladd 2014/01/03 00:57:28 what is a stream?
mem 2014/01/03 17:38:02 Done.
317 Standard input is a
318 <a href="https://api.dartlang.org/dart_async/Stream.html" target="_blank">Stream </a>.
319 That is, the
320 <a href="https://api.dartlang.org/dart_io/Stdin.html" target="_blank">Stdin</a> class
321 is a subclass of the Stream class.
322
323 | Stream | Description |
324 |---|---|
325 | <a href="https://api.dartlang.org/dart_io.html#stdout" target="_blank">stdout< /a> | The standard output |
326 | <a href="https://api.dartlang.org/dart_io.html#stderr" target="_blank">stderr< /a> | The standard error |
327 | <a href="https://api.dartlang.org/dart_io.html#stdin" target="_blank">stdin</a > | The standard input |
328 {: .table }
329
330 ### stdout
sethladd 2014/01/03 00:57:28 maybe add an aside about print(), and when to use
mem 2014/01/03 17:38:02 Done.
331
332 Here's the code from the `dcat` program that writes the line number to the `stdo ut`
333 (if the -n flag is set) followed by the line from the file.
334
335 {% prettify dart %}
336 if (showLineNumbers) {
337 [[highlight]]stdout.write('${lineNumber++} ');[[/highlight]]
338 }
339
340 [[highlight]]stdout.writeln(line);[[/highlight]]
341 {% endprettify %}
342
343 The `write()` and `writeln()` methods take an object of any type,
344 convert it to a string, and print it. The `writeln()` method
345 also prints a newline character.
346 `dcat` uses the `write()` method to print the line number so the
347 line number and the text appear on the same line.
348
349 You can also use the `writeAll()` method to print a list of objects,
350 or use `addStream()` to asynchronously print all of the elements from a stream.
351
352 ### stderr
353
354 Use `stderr` to write error messages to the console.
355 The standard error stream has the same methods as `stdout`,
356 and you use it in the same way.
357 Although both `stdout` and `stderr` print to the console
358 their output is separate
359 and can be redirected or piped at the command line
360 or programmatically to different destinations.
361
362 This code from `dcat` prints an error message if the user
363 tries to list a directory or if the file is not found.
364
365 {% prettify dart %}
366 if (isDir) {
367 [[highlight]]stderr.writeln('error: $path is a directory');[[/highlight]]
368 } else {
369 [[highlight]]stderr.writeln('error: $path not found');[[/highlight]]
370 }
371 {% endprettify %}
372
373 ### stdin
sethladd 2014/01/03 00:57:28 I think it would be nice to bring these sub-sectio
mem 2014/01/03 17:38:02 Done.
374
375 The standard input stream typically
376 reads data synchronously from the keyboard,
377 although it can read asynchronously
378 and it can get input piped in from the standard
379 output of another program.
380
381 Here's a small program that reads a single line from `stdin`:
382
383 {% prettify dart %}
384 import 'dart:io';
385
386 void main() {
387 stdout.writeln('Type something');
388 String input = stdin.readLineSync();
389 stdout.writeln('You typed: $input');
390 }
391 {% endprettify %}
392
393 The `readLineSync()` method reads text from the standard input stream,
394 blocking until the user types in text and presses return.
395 This little program prints out the typed text.
396
397 In the `dcat` program,
398 if the user does not provide a filename on the command line,
399 the program instead reads synchronously from stdin
400 using the `pipe()` method.
401
402 {% prettify dart %}
403 return [[highlight]]stdin[[/highlight]].pipe(stdout);
404 {% endprettify %}
405
406 In this case,
407 the user types in lines of text and the program copies them to stdout.
408 The user signals the end of input by typing &lt;ctl-d&gt;.
409
410 {% prettify bash %}
411 $ [[highlight]]dart dcat.dart[[/highlight]]
412 [[highlight]]The quick brown fox jumped over the lazy dog.[[/highlight]]
413 The quick brown fox jumped over the lazy dog.
414 ...
415 {% endprettify %}
416
417 ## Getting info about a file {#filesystementity}
418
419 The
420 <a href="https://api.dartlang.org/dart_io/FileSystemEntity.html" target="_blank" >FileSystemEntity</a>
421 class in the dart:io library provides
422 properties and static methods that help you inspect and manipulate the file syst em.
423
424 For example, if you have a path,
425 you can determine whether the path is a file, a directory, a link, or not found
426 by using the `type()` method from the `FileSystemEntity` class.
427 Because the `type()` method accesses the file system,
428 it performs the check asynchronously within a Future.
429
430 The following code from
431 the `dcat` example uses `FileSystemEntity` to determine if the path provided
432 on the command line is a directory.
433 The Future returns a boolean that indicates
434 if the path is a directory or not.
435
436 {% prettify dart %}
437 [[highlight]]FileSystemEntity.isDirectory(path)[[/highlight]].then((isDir) {
438 if (isDir) {
439 stderr.writeln('error: $path is a directory');
440 } else {
441 stderr.writeln('error: $path not found');
442 }
443 exit(2);
444 });
445 {% endprettify %}
446
447 Other interesting methods in the `FileSystemEntity` class
448 include `isFile()`, `exists()`, `stat()`, `delete()`,
449 and `rename()`,
450 all of which also use a Future to return a value.
451
452 FileSystemEntity is the superclass for the File, Directory, and Link classes.
453
454 ## Reading a file {#reading-a-file}
455
456 `dcat` opens each file listed on the command line
457 with the `openRead()` method,
458 which returns a stream.
459 The `listen()` method registers a callback function that runs
460 when data becomes available on the stream.
461 The callback function writes that data to stdout.
462
463 {% prettify dart %}
464 return Future.forEach(paths, (path) {
465 int lineNumber = 1;
466 Stream<List<int>> stream = new File(path).openRead();
467
468 return stream
469 ...
470 [[highlight]].listen((line) {
471 if (showLineNumbers) {
472 stdout.write('${lineNumber++} ');
473 }
474 stdout.writeln(line);
475 })[[/highlight]].asFuture()
476 .then((_) { exitCode = 1; })
477 .catchError((_) => _handleError(path));
478 });
479 {% endprettify %}
480
481 This code uses two decoders that transform the data before the
482 `listen()` callback function runs.
483 The UTF8 decoder converts the data into Dart strings.
484 `LineSplitter` splits the data at newlines.
485
486 {% prettify dart %}
487 return Future.forEach(paths, (path) {
488 int lineNumber = 1;
489 Stream<List<int>> stream = new File(path).openRead();
490
491 return stream
492 [[highlight]].transform(UTF8.decoder)
493 .transform(const LineSplitter())[[/highlight]]
494 .listen((line) {
495 if (showLineNumbers) {
496 stdout.write('${lineNumber++} ');
497 }
498 stdout.writeln(line);
499 }).asFuture()
500 .then((_) { exitCode = 1; })
501 .catchError((_) => _handleError(path));
502 });
503 {% endprettify %}
504
505 The dart:convert library contains these and other data converters, including
506 one for JSON.
507 To use these converters you need to import the dart:convert library:
508
509 {% prettify dart %}
510 import 'dart:convert';
511 {% endprettify %}
512
513 ## Writing a file {#writing-a-file}
514
515 The easiest way to write text to a file is to
516 create a
517 <a href="https://api.dartlang.org/dart_io/File.html" target="_blank">File</a>
518 object and use the `writeAsString()` method:
519
520 {% prettify dart %}
521 File quotesFile = new File('quotes.txt');
522 String stronger = 'That which does not kill us makes us stronger. -Nietzsche';
523
524 quotesFile.writeAsString(stronger, mode: FileMode.APPEND)
525 .then((_) { print('Data written.'); });
526 {% endprettify %}
527
528 The `writeAsString()` method writes the data asynchronously via a Future.
529 It opens the file before writing and closes the file when done.
530 To append data to an existing file, you can use the optional
531 parameter `mode` and set its value to `FileMode.APPEND`.
532 Otherwise, the mode is `FileMode.WRITE` and the previous contents of the file,
533 if any, are overwritten.
534
535 If you want to write more data, you can open the file for writing.
536 The `openWrite()` method returns an IOSink (the same type as stdin and stderr).
537 You can continue to write to the file until done,
538 at which time, you must close the file.
539 The `close()` method is asynchronous and returns a Future.
540
541 {% prettify dart %}
542 IOSink quotes = new File('quotes.txt').openWrite(mode: FileMode.APPEND);
543
544 quotes.write('A woman is like a tea bag; ');
545 quotes.write("you never know how strong it is until it's in hot water.");
546 quotes.writeln(" -Eleanor Roosevelt");
547 quotes.close().then((_) { print('done'); } );
548 {% endprettify %}
549
550 ## Getting environment information {#env-var}
551
552 Use the
553 <a href="https://api.dartlang.org/dart_io/Platform.html" target="_blank">Platfor m</a>
554 class
555 to get information about the machine and OS that the program is running on.
556 Note: Use the Platform class from the dart:io library,
557 not from the dart:html library.
558
559 The `environment` property returns a Map that contains all
560 the environment variables currently set.
561
562 {% prettify dart %}
563 Map environmentVars = Platform.environment;
564
565 print('PWD = ${environmentVars["PWD"]}');
566 print('LOGNAME = ${environmentVars["LOGNAME"]}');
567 print('PATH = ${environmentVars["PATH"]}');
568
569 environmentVars['MEANINGOFLIFE'] = 42; // Not persistent.
570
571 print('MEANINGOFLIFE = ${environmentVars["MEANINGOFLIFE"]}');
572 {% endprettify %}
573
574 As you can see from the code, you can change values
575 in the Map. However, these do not persist. If you refer to
sethladd 2014/01/03 00:57:28 persist is a bit overloaded. I think this is a bug
mem 2014/01/03 17:38:02 Done.
576 `Platform.environment` again, your changes will not be there.
577
578 `Platform` provides other useful properties that give
579 information about the machine, OS, and currently
580 running program.
581 For example:
582
583 * `Platform.isMacOS()`
584 * `Platform.numberOfProcessors`
585 * Platform.script.path
586
587 ## Setting exit codes {#exit-codes}
588
589 The dart:io library defines a top-level property,
590 `exitCode`, that you can change to set the exit code for
sethladd 2014/01/03 00:57:28 define what an exit code is
mem 2014/01/03 17:38:02 Done.
591 the current invocation of the Dart VM.
592
593 The `dcat` example sets the program's exit code
594 in two different places.
595 First, at the very beginning of `main()`,
596 the program sets the exit code to 0.
597
598 {% prettify dart %}
599 ...
600 void main(List<String> arguments) {
601 exitCode = 0; // Presume success.
sethladd 2014/01/03 00:57:28 weird that it sets it to zero at the beginning.
mem 2014/01/03 17:38:02 Done.
602 ...
603 }
604 ...
605 {% endprettify %}
606
607 The last assignment to `exitCode` provides the final exit code for the program.
608 So, if the `dcat` program does not set the exit code again,
609 it exits with a code of 0, which indicates success.
610
611 Second, the program sets the error code
612 in the `_handleError()` function.
613
614 {% prettify dart %}
615 _handleError(String path) {
616 FileSystemEntity.isDirectory(path).then((isDir) {
617 if (isDir) {
618 stderr.writeln('error: $path is a directory');
619 } else {
620 stderr.writeln('error: $path not found');
621 }
622 [[highlight]]exitCode = 2;[[/highlight]]
623 });
624 }
625 {% endprettify %}
626
627 An exit code of 2 indicates that the program encountered an error.
628
629 An alternative to using `exitCode` is to use the top-level `exit()` function,
630 which sets the exit code and quits the program immediately.
631 For example, the `_handleError()` function could call `exit(2)
sethladd 2014/01/03 00:57:28 missing a closing `
mem 2014/01/03 17:38:02 Done.
632 instead of setting `exitCode` to 2.
633 Generally speaking, you are better off using the `exitCode` property,
sethladd 2014/01/03 00:57:28 make this bolder, more obvious. Do we have a "Mary
mem 2014/01/03 17:38:02 Done.
634 which sets the exit code but allows the program to continue through to its
635 natural completion.
636
637 Although you can use any number for an exit code,
638 by convention, the codes in the table below have the following meanings:
639
640 | Code | Meaning |
641 |---|---|
642 | 0 | Success |
643 | 1 | Warnings |
644 | 2 | Errors |
645 {: .table }
646
647 ### Another example: dgrep {#dgrep-code}
sethladd 2014/01/03 00:57:28 I think this is the wrong header level? Too low.
sethladd 2014/01/03 00:57:28 Consider dropping this section. It doesn't provide
mem 2014/01/03 17:38:02 Done.
mem 2014/01/03 17:38:02 Done.
mem 2014/01/03 17:38:02 Done.
648
649 Here's the code for `dgrep`, a simplified version of the Unix utility grep
sethladd 2014/01/03 00:57:28 Again, what is grep?
mem 2014/01/03 17:38:02 Done.
mem 2014/01/03 17:38:02 Done.
650 called `dgrep`.
651 This program makes use of some additional APIs that don't
sethladd 2014/01/03 00:57:28 instead of "additional APIs", how about enumeratin
mem 2014/01/03 17:38:02 Done.
652 appear in the `dcat` example.
653
654 <pre class="prettyprint lang-dart">
655 import 'dart:io';
656 import 'package:args/args.dart';
657
658 const USAGE = 'usage: dart dgrep.dart [-rnS] patterns file_or_directory';
659 const RECURSIVE = 'recursive';
660 const LINE_NUMBER = 'line-number';
661 const FOLLOW_LINKS = 'follow-links';
662
663 ArgResults argResults;
664
665 void main(List&lt;String&gt; arguments) {
666 final parser = new ArgParser()
667 ..addFlag(RECURSIVE, negatable: false, abbr: 'r')
668 ..addFlag(LINE_NUMBER, negatable: false, abbr: 'n')
669 ..addFlag(FOLLOW_LINKS, negatable: false, abbr: 'S');
670
671 argResults = parser.parse(arguments);
672
673 if (argResults.rest.length &lt; 2) {
674 print(USAGE);
675 exit(1);
676 }
677
678 final searchPath = <a href="#" class="dart-popover" data-toggle="popover" titl e="The rest property is a List." data-html="true" data-trigger="hover focus" dat a-content="ArgResults.rest is a list. Use the last property to get the last comm and-line argument.">argResults.rest.last;</a>
sethladd 2014/01/03 00:57:28 not that interesting, consider dropping (it's not
mem 2014/01/03 17:38:02 Done.
679 final searchTerms = argResults.rest.sublist(0, argResults.rest.length - 1);
680
681 FileSystemEntity.isDirectory(searchPath).then((isDir) {
682 if (isDir) {
683 final startingDir = <a href="#" class="dart-popover" data-toggle="popover" title="Create a Directory" data-html="true" data-trigger="hover focus" data-con tent="Create a new Directory object at the specified path.">new Directory(search Path);</a>
684 <a href="#" class="dart-popover" data-toggle="popover" title="Recursive di rectory search" data-html="true" data-trigger="hover focus" data-content="List a directory's subdirectories recursively and process each file within.">startingD ir.list(recursive: argResults[RECURSIVE],
685 followLinks: argResults[FOLLOW_LINKS]).listen((entity)</a > {
686 if (entity is File) {
687 searchFile(entity, searchTerms);
688 }
689 });
690 } else {
691 searchFile(<a href="#" class="dart-popover" data-toggle="popover" title="C reate a File" data-html="true" data-trigger="hover focus" data-content="Create a new file at the specified path.">new File(searchPath)</a>, searchTerms);
sethladd 2014/01/03 00:57:28 This doesn't actually create a new file. I don't t
mem 2014/01/03 17:38:02 Done.
692 }
693 });
694 }
695
696
697 void printMatch(File file, List lines, int i) {
698 StringBuffer sb = new StringBuffer();
699 if (argResults[RECURSIVE]) sb.write('${file.path}:');
700 if (argResults[LINE_NUMBER]) sb.write('${i + 1}:');
701 sb.write(lines[i]);
702 print(sb.toString());
703 }
704
705 searchFile(File file, searchTerms) {
706 <a href="#" class="dart-popover" data-toggle="popover" title="Read a file as l ines" data-html="true" data-trigger="hover focus" data-content="Read a file as a list of strings that contains each line separately.">file.readAsLines()</a>.the n((lines) {
707 for (var i = 0; i &lt; lines.length; i++) {
708 bool found = false;
709 for (var j = 0; j &lt; searchTerms.length &amp;&amp; !found; j++) {
710 if (lines[i].contains(searchTerms[j])) {
711 printMatch(file, lines, i);
712 found = true;
713 }
714 }
715 }
716 }).catchError(print);
717 }
718
719 </pre>
720
721 ## Summary {#summary}
722
723 This tutorial described some basic API found in these classes from the dart:io l ibrary:
724
725 | API | Description |
726 |---|---|
727 | <a href="https://api.dartlang.org/dart_io/IOSink.html" target="_blank">IOSink< /a> | Helper class for objects that consume data from streams. |
728 | <a href="https://api.dartlang.org/dart_io/File.html" target="_blank">File</a> | Represents a file on the native file system |
729 | <a href="https://api.dartlang.org/dart_io/Directory.html" target="_blank">Dire ctory</a> | Represents a directory on the native file system |
730 | <a href="https://api.dartlang.org/dart_io/FileSystemEntity.html" target="_blan k">FileSystemEntity</a> | Superclass for File and Directory |
731 | <a href="https://api.dartlang.org/dart_io/Platform.html" target="_blank">Platf orm</a> | Provides information about the machine and operating system |
732 | <a href="https://api.dartlang.org/dart_io.html#stdout" target="_blank">stdout< /a> | The standard output |
733 | <a href="https://api.dartlang.org/dart_io.html#stderr" target="_blank">stderr< /a> | The standard error |
734 | <a href="https://api.dartlang.org/dart_io.html#stdin" target="_blank">stdin</a > | The standard input |
735 | <a href="https://api.dartlang.org/dart_io.html#exitCode" target="_blank">exitC ode</a> | Sets the exit code |
736 | <a href="https://api.dartlang.org/dart_io.html#exit" target="_blank">exit()</a > | Sets the exit code and quits |
737 {: .table }
738
739 In addition, this tutorial covers two classes that help with command-line argume nts:
740
741 | Class | Description |
742 |---|---|
743 | <a href="https://api.dartlang.org/args/ArgParser" target="_blank">ArgParser</a > | A class that transforms a list of raw arguments and into a set of options, f lags, and remaining values. |
744 | <a href="https://api.dartlang.org/args/ArgResults" target="_blank">ArgResults< /a> | The result of parsing raw command line arguments using ArgParser. |
745 {: .table }
746
747 ## Other resources {#other-resources}
748
749 See the
750 [Dartiverse Search walkthrough](/docs/dart-up-and-running/contents/ch05.html)
751 for an example of another kind of command-line app: an HTTP server.
752
753 Refer to the API docs for <a href="https://api.dartlang.org/dart_io.html" target ="_blank">dart:io</a>,
754 <a href="https://api.dartlang.org/dart_async.html" target="_blank">dart:async</a >,
755 <a href="https://api.dartlang.org/dart_convert.html" target="_blank">dart:conver t</a>,
756 and the
757 <a href="https://api.dartlang.org/dart_args.html" target="_blank">args</a>
758 package for more classes, functions, and properties.
759
760 ## What next? {#what-next}
761
762 The [Get Input from a Form](/docs/tutorials/forms/) tutorial
763 features a client-server.
764 The code for the server, which uses CORS headers and handles
765 POST requests, is explained in detail.
766
767 {% endcapture %}
768
769 {% include tutorial.html %}
OLDNEW
« no previous file with comments | « src/site/docs/tutorials/cmdline/images/sourceforhomepage.png ('k') | src/site/docs/tutorials/index.markdown » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698