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

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: Created 7 years 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 %}
15
16 * Server-side applications need to do input and output.
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?
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 command-line apps</h3>
Kathy Walrath 2013/12/20 23:12:16 change "command-line apps" to something else. (not
mem 2013/12/30 22:17:13 Done.
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.
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 code](#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 * [Other resources](#other-resources)
77 * [What next?](#what-next)
78
79 ## Run an app with the standalone Dart VM {#run-the-first-app}
80
81 To run a command-line app, you need the Dart VM,
Kathy Walrath 2013/12/20 23:12:16 VM, -> VM (`dart`),
mem 2013/12/30 22:17:13 Done.
82 which comes with the Dart Editor or the Dart SDK download.
Kathy Walrath 2013/12/20 23:12:16 -> which comes with the Dart Editor (in the Dart d
mem 2013/12/30 22:17:13 Done.
83 For example,
84 suppose you installed the Dart download in a directory called `~/myDartDownload` ,
Kathy Walrath 2013/12/20 23:12:16 For example, suppose you installed -> If you insta
mem 2013/12/30 22:17:13 Done.
85 you can find the Dart VM, called `dart`,
Kathy Walrath 2013/12/20 23:12:16 the Dart VM, called `dart`, -> `dart`
mem 2013/12/30 22:17:13 Done.
86 in `~/myDartDownload/dart-sdk/bin`.
87
88 <div markdown="1">
89
90 ![The path to the Dart VM](images/filestructure.png)
91
92 </div>
93
94 By putting this directory in your PATH
95 you can refer to the `dart` command and other commands,
96 such as the dart analyzer, by name.
97
98 Let's run a small program.
99
100 <ol>
101 <li markdown="1">
102 Create a file called `helloworld.dart` that contains this code:
103
104 {% prettify dart %}
105 void main() {
106 int fortyTwo = 'Hello, World'; // Type mis-match
Kathy Walrath 2013/12/20 23:12:16 mis-match -> mismatch (GLOBAL)
mem 2013/12/30 22:17:13 Done.
107 print(fortyTwo);
108 }
109 {% endprettify %}
110 </li>
111
112 <li markdown="1">
113 In the directory that contains the file you just created,
114 run the program with the command as shown by the highlighted text.
115
116 {% prettify bash %}
117 % [[highlight]]dart helloworld.dart[[/highlight]]
118 Hello, World!
119 %
120 {% endprettify %}
121
122 The program runs cleanly in spite
123 of the type mis-match in the source code.
124 Types are optional in Dart and by default the Dart VM
125 does not do type-checking.
126 </li>
127
128 <li markdown="1">
129 Run the `helloworld.dart` program using the `--checked` flag:
130
131 {% prettify bash %}
132 % [[highlight]]dart --checked helloworld.dart[[/highlight]]
133 Unhandled exception:
134 type 'String' is not a subtype of type 'int' of 'fortyTwo'.
135 ...
136 %
137 {% endprettify %}
138
139 The program fails because the program assigns a string to an integer.
140
141 The `--checked` option enables
142 assertion and type checks (checked mode).
143 Checked mode is useful during production for finding errors
Kathy Walrath 2013/12/20 23:12:16 production -> development
mem 2013/12/30 22:17:13 Done.
144 related to types and for testing `assert` statements.
145 We recommend running your programs in checked mode during prototyping
146 and development and turning it off for production.
147
148 Note that the flags and options passed to the Dart VM go before the name
149 of the Dart file to run.
150 </li>
151 </ol>
152
153 ## Check out the dcat code {#dcat-code}
154
155 Take a quick look at the code for a small sample called `dcat`,
156 which is a simplified implementation of the Unix cat utility.
157 This program uses various classes, functions, and properties
158 available to command-line apps, which this tutorial explains.
Kathy Walrath 2013/12/20 23:12:16 delete ", which this..." Maybe tell people to hov
mem 2013/12/30 22:17:13 Done.
159
160 <pre class="prettyprint lang-dart">
161 import 'dart:async';
162 import 'dart:convert';
163 import 'dart:io';
164
165 import 'package:args/args.dart';
166
167 const LINE_NUMBER = 'line-number';
168 var NEWLINE = '\n';
169
170 ArgResults argResults;
171
172 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>) {
173 exitCode = 0; //presume success.
174 final parser = new ArgParser()
175 ..addFlag(LINE_NUMBER, negatable: false, abbr: 'n');
176
177 <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>
178 List&lt;String&gt; paths = argResults.rest;
179
180 dcat(paths, argResults[LINE_NUMBER]);
181 }
182
183 Future dcat(List&lt;String&gt; paths, bool showLineNumbers) {
184 if (paths.isEmpty) {
185 // No files provided as arguments. Read from stdin and print each line.
186 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>
187 } else {
188 return Future.forEach(paths, (path) {
189 int lineNumber = 1;
190 <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>
191 return stream
192 <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>
193 .transform(const LineSplitter())
194 <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> {
195 if (showLineNumbers) {
196 stdout.write('${lineNumber++} ');
197 }
198 stdout.writeln(line);
199 }).asFuture().catchError((_) =&gt; _handleError(path));
200 });
201 }
202 }
203
204 _handleError(String path) {
205 <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) {if (isDir) {
Kathy Walrath 2013/12/20 23:12:16 if (isDir) { should be on its own line, right?
mem 2013/12/30 22:17:13 Done.
206 print('error: $path is a directory');
207 } else {
208 print('error: $path not found');
209 }
210 });
211 <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>
212 }
213
214 </pre>
215
216 ## Parsing command-line arguments {#cmd-line-args}
217
218 The
219 <a href="https://api.dartlang.org/args.html" target="_blank">args</a>
220 package provides
221 parser support for transforming raw command-line arguments
222 into a set of options, flags, and additional values.
223 Import the library as follows:
224
225 {% prettify dart %}
226 import 'package:args/args.dart';
227 {% endprettify %}
228
229 The args library contains two classes:
230
231 | Library | Description |
232 |---|---|
233 | <a href="https://api.dartlang.org/args/ArgParser" target="_blank">ArgParser</a > | A class that parses command-line arguments |
234 | <a href="https://api.dartlang.org/args/ArgResults" target="_blank">ArgResults< /a> | The result of parsing command-line arguments using ArgParser. |
235 {: .table }
236
237 Let's take a look at the `dcat` sample
Kathy Walrath 2013/12/20 23:12:16 sample -> sample,
mem 2013/12/30 22:17:13 Done.
238 which uses ArgParser and ArgResults to parse and store its command-line argument s.
239
240 <ol>
241 <li markdown="1">
242 Copy the sample file from the github repo:
243 <a href="https://github.com/dart-lang/dart-tutorials-samples/blob/master/bin/dca t.dart">dcat.dart</a>.
244 </li>
245
246 <li markdown="1">
247 Run the program from the command-line as shown by the highlighted text.
Kathy Walrath 2013/12/20 23:12:16 command-line -> command line (since it's not an a
mem 2013/12/30 22:17:13 Done.
248
249 {% prettify bash %}
Kathy Walrath 2013/12/20 23:12:16 Weirdly, this highlights seemingly random words, s
250 $ [[highlight]]dart dcat.dart -n dcat.dart[[/highlight]]
Kathy Walrath 2013/12/20 23:12:16 I found the -n dcat.dart confusing, since dcat.dar
mem 2013/12/30 22:17:13 Done.
251 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
252 2 // for details. All rights reserved. Use of this source code is governed by a
253 3 // BSD-style license that can be found in the LICENSE file.
254 ...
255 {% endprettify %}
256
257 The program displays the contents of the source code file and
258 preceeds each line with a line number.
259 </li>
260
261 </ol>
262
263 The following diagram shows how the `dcat` command line used above
264 is parsed into the `ArgResults` object.
265
266 ![ArgsParser parses command-line arguments](images/commandlineargs.png)
267
268 You can access flags and options by name,
269 treating the ArgResults object like a Map.
270 You can access other values with properties such as `rest`.
271
272 Here's the code from `dcat` that deals with command-line arguments:
273
274 <pre class="prettyprint lang-dart">
275
276 ...
277 <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>
278
279 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>) {
Kathy Walrath 2013/12/20 23:12:16 command line -> command-line :)
mem 2013/12/30 22:17:13 Done.
280 final parser = new ArgParser()
281 <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>;
282
283 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>;
284 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>;
285
286 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>;
287 }
288 ...
289 </pre>
290
291 The API docs for the
292 <a href="https://api.dartlang.org/args.html" target="_blank">args</a> library
Kathy Walrath 2013/12/20 23:12:16 This link should be on API docs (and why isn't it
mem 2013/12/30 22:17:13 it's not in markdown because I want to use target=
293 provides very detailed information
Kathy Walrath 2013/12/20 23:12:16 provides very -> provide
mem 2013/12/30 22:17:13 Done.
294 about the use of the ArgsParser and ArgResults classes.
Kathy Walrath 2013/12/20 23:12:16 about the use of -> to help you use OR about using
mem 2013/12/30 22:17:13 Done.
295
296 ## Reading and writing with stdin, stdout, and stderr {#std-in-out-err}
297
298 Like other languages,
299 Dart has standard output, standard error, and standard input streams.
300 The standard I/O streams are defined at the top-level of the dart:io library,
Kathy Walrath 2013/12/20 23:12:16 top-level -> top level
mem 2013/12/30 22:17:13 Done.
301 which you import as follows:
302
303 {% prettify dart %}
304 import 'dart:io';
305 {% endprettify %}
306
307 Only command-line applications, not web applications,
308 can use the dart:io library.
309
310 Standard output and standard error are
311 <a href="https://api.dartlang.org/dart_io/IOSink.html" target="_blank">IOSink</a >s
312 rather than streams, but can be bound to a stream.
313 Standard input is a
314 <a href="https://api.dartlang.org/dart_async/Stream.html" target="_blank">Stream </a>.
315 That is, the
316 <a href="https://api.dartlang.org/dart_io/Stdin.html" target="_blank">Stdin</a> class
317 is a subclass of the Stream class.
318
319 | Library | Description |
Kathy Walrath 2013/12/20 23:12:16 Library -> Object?
mem 2013/12/30 22:17:13 Done.
320 |---|---|
321 | <a href="https://api.dartlang.org/dart_io.html#stdout" target="_blank">stdout< /a> | The standard output |
322 | <a href="https://api.dartlang.org/dart_io.html#stderr" target="_blank">stderr< /a> | The standard error |
323 | <a href="https://api.dartlang.org/dart_io.html#stdin" target="_blank">stdin</a > | The standard input |
324 {: .table }
325
326 ### stdout
327
328 Here's the code from the `dcat` program that writes the line number to the `stdo ut`
329 (if the -n flag is set) followed by the line from the file.
330
331 {% prettify dart %}
332 if (showLineNumbers) {
333 [[highlight]]stdout.write('${lineNumber++} ');[[/highlight]]
334 }
335
336 [[highlight]]stdout.writeln(line);[[/highlight]]
337 {% endprettify %}
338
339 The `write()` and `writeln()` methods take an object of any type,
340 convert it to a string, and print it. The `writelin()` method
Kathy Walrath 2013/12/20 23:12:16 lin -> ln
mem 2013/12/30 22:17:13 Done.
mem 2013/12/30 22:17:13 Done.
341 also prints a newline character.
342 `dcat` uses the `write()` method to print the line number so the
343 line number and the text appear on the same line.
344
345 You can also use the `writeAll()` method to print a list of objects,
346 or use `addStream()` to asynchronously print all of the elements from a stream.
347
348 ### stderr
349
350 Use `stderr` to write error messages to the console.
351 The standard error stream has the same methods as `stdout`,
352 and you use it in the same way.
353 Although both `stdout` and `stderr` print to the console
354 their output is separate
355 and can be redirected or piped at the command-line to different destinations.
Kathy Walrath 2013/12/20 23:12:16 no - in command-line here!
mem 2013/12/30 22:17:13 Done.
356
357 This code from `dcat` prints an error message if the user
358 tries to list a directory or if the file is not found.
359
360 {% prettify dart %}
361 if (isDir) {
362 [[highlight]]stderr.writeln('error: $path is a directory');[[/highlight]]
363 } else {
364 [[highlight]]stderr.writeln('error: $path not found');[[/highlight]]
365 }
366 {% endprettify %}
367
368 ### stdin
369
370 The standard input stream typically
371 reads data synchronously from the keyboard,
372 although it can read asynchronously
373 and it can get input piped in from the standard
374 output of another program.
375
376 Here's a small program that reads a single line from `stdin`:
377
378 {% prettify dart %}
379 import 'dart:io';
380 import 'dart:async';
381
382 void main() {
383 stdout.writeln('What's in a name?');
Kathy Walrath 2013/12/20 23:12:16 's => \'s? (This doesn't work as written, right?)
mem 2013/12/30 22:17:13 Done.
384 [[highlight]]String path = stdin.readLineSync();[[/highlight]]
385
386 FileSystemEntity.type(path).then((type) {
387 print(type);
388 });
389 }
390 {% endprettify %}
391
392 The `readLineSync()` method reads text from the standard input stream
Kathy Walrath 2013/12/20 23:12:16 stream -> stream,
mem 2013/12/30 22:17:13 Done.
393 blocking until the user types in text and presses return.
394 This little program assumes the input is a pathname and prints out what
395 type of file system entity the path points to.
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 [[highlight]]ctl-d[[/highlight]]
Kathy Walrath 2013/12/20 23:12:16 ctl-d -> <ctl-d> ? (so it'll match the descriptio
mem 2013/12/30 22:17:13 the &lt; and gt& signs don't work with highlight.
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 methods that help you inspect and manipulate the file system.
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.
Kathy Walrath 2013/12/20 23:12:16 It's a little weird that we've already seen this.
mem 2013/12/30 22:17:13 Done.
426 As you saw in the previous example,
427 you can use the `type()` method from the `FileSystemEntity` class.
Kathy Walrath 2013/12/20 23:12:16 This is linked to the previous example, but not to
mem 2013/12/30 22:17:13 Done.
428 Because the `type` method accesses the file system,
Kathy Walrath 2013/12/20 23:12:16 type or type()?
mem 2013/12/30 22:17:13 Done.
429 it performs the check asynchronously within a Future.
430
431 The following code from
432 the `dcat` example uses `FileSystemEntity` to determine if the path provided
433 on the command-line is a directory.
Kathy Walrath 2013/12/20 23:12:16 command-line -> command line
mem 2013/12/30 22:17:13 Done.
434 The Future returns a boolean to the `then()` method that indicates
Kathy Walrath 2013/12/20 23:12:16 It's not actually returned to the then() method. I
mem 2013/12/30 22:17:13 Done.
435 if the path is a directory or not.
436
437 {% prettify dart %}
438 [[highlight]]FileSystemEntity.isDirectory(path)[[/highlight]].then((isDir) {
439 if (isDir) {
440 stderr.writeln('error: $path is a directory');
441 } else {
442 stderr.writeln('error: $path not found');
443 }
444 exit(2);
445 });
446 {% endprettify %}
447
448 Other interesting methods in the `FileSystemEntity` class
449 include `isFile()`, `exists()`, `stat()` and `parent`,
Kathy Walrath 2013/12/20 23:12:16 and -> , and
mem 2013/12/30 22:17:13 Done.
450 all of which also use a Future to return a value.
451 `FileSystemEntity` also provides methods for deleting a file
452 and renaming a file.
Kathy Walrath 2013/12/20 23:12:16 Do they not return Futures? Or are there multiple
mem 2013/12/30 22:17:13 Done.
453
454 ## Reading a file {#reading-a-file}
455
456 For each file listed on the command-line `dcat` opens it for reading
Kathy Walrath 2013/12/20 23:12:16 This sentence needs a little work, grammatically.
mem 2013/12/30 22:17:13 Done.
mem 2013/12/30 22:17:13 Done.
457 with the `openRead()` method.
458 This returns a stream.
Kathy Walrath 2013/12/20 23:12:16 Seems awkward. Combine with previous sentence?
mem 2013/12/30 22:17:13 Done.
459 The `listen()` method registers a callback function that runs
460 when data becomes available on the stream.
461
462 The callback function provided by `dcat` writes the data to stdout.
Kathy Walrath 2013/12/20 23:12:16 This is a little disjointed. It's unclear why it's
mem 2013/12/30 22:17:13 Done.
463
464 {% prettify dart %}
465 return Future.forEach(paths, (path) {
466 int lineNumber = 1;
467 Stream<List<int>> stream = new File(path).openRead();
468
469 return stream
470 ...
471 [[highlight]].listen((line)[[/highlight]] {
472 if (showLineNumbers) {
473 stdout.write('${lineNumber++} ');
474 }
475 stdout.writeln(line);
476 }).asFuture().then((_) { exitCode = 1; }).catchError((_) => _handleError(p ath));
Kathy Walrath 2013/12/20 23:12:16 reduce the line length here
mem 2013/12/30 22:17:13 Done.
477 });
478 {% endprettify %}
479
480 This code uses two decoders that transform the data before the
481 `listen()` callback function runs.
482 The UTF8 decoder converts the data into Dart strings.
483 `LineSplitter` splits the data at newlines.
484
485 {% prettify dart %}
486 return Future.forEach(paths, (path) {
487 int lineNumber = 1;
488 Stream<List<int>> stream = new File(path).openRead();
489
490 return stream
491 [[highlight]].transform(UTF8.decoder)
492 .transform(const LineSplitter())[[/highlight]]
493 .listen((line) {
494 if (showLineNumbers) {
495 stdout.write('${lineNumber++} ');
496 }
497 stdout.writeln(line);
498 }).asFuture().then((_) { exitCode = 1; }).catchError((_) => _handleError(p ath));
Kathy Walrath 2013/12/20 23:12:16 another too-long line
mem 2013/12/30 22:17:13 Done.
499 });
500 {% endprettify %}
501
Kathy Walrath 2013/12/20 23:12:16 including -> , including
mem 2013/12/30 22:17:13 Done.
502 The dart:convert library contains these and other data converters including
503 one for JSON.
504 To use these converters you need to import the dart:convert library:
505
506 {% prettify dart %}
507 import 'dart:convert';
508 {% endprettify %}
509
510 ## Writing a file {#writing-a-file}
511
512 The easiest way to write text to a file is to
513 create a
514 <a href="https://api.dartlang.org/dart_io/File.html" target="_blank">
515 File
Kathy Walrath 2013/12/20 23:12:16 remove newline after File
mem 2013/12/30 22:17:13 Done.
516 </a>
517 object and use the `writeAsString()` method:
518
519 {% prettify dart %}
520 File quotesFile = new File('quotes.txt');
521 String stronger = 'That which does not kill us makes us stronger. -Friedrich Nie tzsche';
Kathy Walrath 2013/12/20 23:12:16 long line
mem 2013/12/30 22:17:13 Done.
522
523 quotesFile.writeAsString(stronger, mode: FileMode.APPEND)
524 .then((_) { print('Data written.'); });
525 {% endprettify %}
526
527 The `writeAsString()` method writes the data asynchronously via a Future.
528 It opens the file before writing and closes the file when done.
529 To append data to an existing file you can use the optional
Kathy Walrath 2013/12/20 23:12:16 long sentence, no commas!
mem 2013/12/30 22:17:13 Done.
530 parameter `mode` and set its value to `FileMode.APPEND` as we've done here.
531 Otherwise, the mode is `FileMode.WRITE` and the previous contents of the file,
532 if there is any, gets overwritten.
Kathy Walrath 2013/12/20 23:12:16 delete "there is" gets -> are
mem 2013/12/30 22:17:13 Done.
533
534 If you want to write more data, you can open the file for writing.
535 The `openWrite()` method returns an IOSink (the same type as stdin and stderr).
536 You can continue to write to the file until done.
Kathy Walrath 2013/12/20 23:12:16 Combine this with the following sentence, to make
mem 2013/12/30 22:17:13 Done.
537 Then you must close the file.
538 The `close()` method is asynchronous and returns a Future.
539
540 {% prettify dart %}
541 IOSink quotes = new File('quotes.txt').openWrite(mode: FileMode.APPEND);
542
543 quotes.write('A woman is like a tea bag; ');
544 quotes.write("you never know how strong it is until it's in hot water.");
545 quotes.writeln(" -Eleanor Roosevelt");
546 quotes.close().then((_) { print('done'); } );
547 {% endprettify %}
548
549 ## Getting environment information {#env-var}
550
551 Use the
552 <a href="https://api.dartlang.org/dart_io/Platform.html" target="_blank">
553 Platform
Kathy Walrath 2013/12/20 23:12:16 remove newline after Platform
mem 2013/12/30 22:17:13 Done.
554 </a>
555 class (from the dart:io library, not from the dart:html library)
Kathy Walrath 2013/12/20 23:12:16 make this io vs. html aside a note, so it doesn't
mem 2013/12/30 22:17:13 Done.
mem 2013/12/30 22:17:13 Done.
556 to get information about the machine and OS that the program is running on.
557
558 The `environmont` property returns a Map that contains all
Kathy Walrath 2013/12/20 23:12:16 environmOnt?
mem 2013/12/30 22:17:13 Done.
559 the environment variables currently set.
560
561 {% prettify dart %}
562 Map environmentVars = Platform.environment;
563
564 print('PWD = ${environmentVars["PWD"]}');
565 print('LOGNAME = ${environmentVars["LOGNAME"]}');
566 print('PATH = ${environmentVars["PATH"]}');
567
568 environmentVars['MEANINGOFLIFE'] = 42; // Not persistent.
569
570 print('MEANINGOFLIFE = ${environmentVars["MEANINGOFLIFE"]}');
571 {% endprettify %}
572
573 As you can see from the code, you can change values
574 in the Map, but these do not persist and if you refer to
Kathy Walrath 2013/12/20 23:12:16 , but -> However, persist and -> persist. If (Yo
mem 2013/12/30 22:17:13 Done.
575 `Platform.environment` again, your changes will not be there.
576
577 `Platform` provides other useful properties that give
578 information about the machine and OS:
Kathy Walrath 2013/12/20 23:12:16 Are the following all of the properties? If so, re
mem 2013/12/30 22:17:13 Done.
579
580 {% prettify dart %}
581 Platform.isMacOS()
582 Platform.isLinux()
Kathy Walrath 2013/12/20 23:12:16 usually we don't use a <pre> section for non-runni
mem 2013/12/30 22:17:13 Done.
583 Platform.isWindows()
584 {% endprettify %}
585
586 Get the path of the currently running program with:
587
588 {% prettify dart %}
Kathy Walrath 2013/12/20 23:12:16 This seems a little weird; it's not code you'd use
mem 2013/12/30 22:17:13 Done.
589 Platform.script.path;
590 {% endprettify %}
591
592 ## Setting exit codes {#exit-codes}
593
594 The dart:io library defines a top-level property
Kathy Walrath 2013/12/20 23:12:16 property -> property,
mem 2013/12/30 22:17:13 Done.
595 `exitCode`, that you can change to set the exit code for
596 the current invocation of the Dart VM.
597
598 The `dcat` example sets the program's exit code
599 in two different places.
600 First, at the very beginning of `main()`,
601 the program sets the exit code to 0.
602
603 {% prettify dart %}
604 ...
605 void main(List<String> arguments) {
606 exitCode = 0; //presume success.
Kathy Walrath 2013/12/20 23:12:16 hmmm... I just noticed that comment format is diff
mem 2013/12/30 22:17:13 Done.
607 ...
608 }
609 ...
610 {% endprettify %}
611
612 The last assignment to `exitCode` provides the final exit code for the program.
613 So, if the `dcat` program does not set the exit code again,
614 it exits with a code of 0, which indicates success.
615
616 Second, the program sets the error code
617 in the `_handleError()` function.
618
619 {% prettify dart %}
620 _handleError(String path) {
621 FileSystemEntity.isDirectory(path).then((isDir) {
622 if (isDir) {
623 stderr.writeln('error: $path is a directory');
624 } else {
625 stderr.writeln('error: $path not found');
626 }
627 [[highlight]]exitCode = 2;[[/highlight]]
628 });
629 }
630 {% endprettify %}
631
632 An exit code of 2 indicates that the program encountered an error.
633
634 An alternative to using `exitCode` is to use the top-level `exit()` function,
635 which sets the exit code and quits the program immediately.
636 For example, the `_handleError` function could use this code
Kathy Walrath 2013/12/20 23:12:16 _handleError -> _handleError()
mem 2013/12/30 22:17:13 Done.
mem 2013/12/30 22:17:13 Done.
637 instead:
638
639 {% prettify dart %}
640 _handleError(String path) {
Kathy Walrath 2013/12/20 23:12:16 I might just put this inline, since you don't enco
mem 2013/12/30 22:17:13 Done.
641 FileSystemEntity.isDirectory(path).then((isDir) {
642 if (isDir) {
643 stderr.writeln('error: $path is a directory');
644 } else {
645 stderr.writeln('error: $path not found');
646 }
647 [[highlight]]exit(2);[[/highlight]]
648 });
649 }
650 {% endprettify %}
651
652 Generally speaking, you are better off using the `exitCode` property,
653 which sets the exit code but allows the program to continue through to its
654 natural completion.
655
656 Although you can use any number for an exit code,
657 these are defined by convention:
Kathy Walrath 2013/12/20 23:12:16 I don't like "these" (or "are defined"). Rewrite i
mem 2013/12/30 22:17:13 Done.
658
659 | Code | Meaning |
660 |---|---|
661 | 0 | Success |
662 | 1 | Warnings |
663 | 2 | Errors |
664 {: .table }
665
666 ## Check out the code for another example {#dgrep-code}
Kathy Walrath 2013/12/20 23:12:16 Maybe just: ## Another example: dgrep {#dgrep-cod
mem 2013/12/30 22:17:13 Done.
667
668 Here's the code for a simplified version of the Unix utility grep
Kathy Walrath 2013/12/20 23:12:16 for a... -> for `dgrep`, a ....
mem 2013/12/30 22:17:13 Done.
669 called `dgrep`.
670 This program makes use of some additional APIs that do not
Kathy Walrath 2013/12/20 23:12:16 do not -> don't
mem 2013/12/30 22:17:13 Done.
671 appear in the `dcat` example.
672
673 <pre class="prettyprint lang-dart">
Kathy Walrath 2013/12/20 23:12:16 why use a <pre> here instead of {% prettify... %}?
mem 2013/12/30 22:17:13 it's necessary for the popups.
674 import 'dart:io';
675 import 'package:args/args.dart';
676
677 const USAGE = 'usage: dart dgrep.dart [-rnS] patterns file_or_directory';
678 const RECURSIVE = 'recursive';
679 const LINE_NUMBER = 'line-number';
680 const FOLLOW_LINKS = 'follow-links';
681
682 ArgResults argResults;
683
684 void main(List&lt;String&gt; arguments) {
685 final parser = new ArgParser()
686 ..addFlag(RECURSIVE, negatable: false, abbr: 'r')
687 ..addFlag(LINE_NUMBER, negatable: false, abbr: 'n')
688 ..addFlag(FOLLOW_LINKS, negatable: false, abbr: 'S');
689
690 argResults = parser.parse(arguments);
691
692 if (argResults.rest.length &lt; 2) {
693 print(USAGE);
694 exit(1);
695 }
696
697 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>
698 final searchTerms = argResults.rest.sublist(0, argResults.rest.length - 1);
699
700 FileSystemEntity.isDirectory(searchPath).then((isDir) {
701 if (isDir) {
702 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 with a pathname.">new Directory(searchPath); </a>
Kathy Walrath 2013/12/20 23:12:16 What does "with a pathname" mean? How does it diff
mem 2013/12/30 22:17:13 Done.
703 <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],
704 followLinks: argResults[FOLLOW_LINKS]).listen((entity)</a > {
705 if (entity is File) {
706 searchFile(entity, searchTerms);
707 }
708 });
709 } else {
710 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 with a path">new File(searchPath)</a>, searchTerms);
Kathy Walrath 2013/12/20 23:12:16 path -> path. maybe: with a path -> at the specif
mem 2013/12/30 22:17:13 Done.
711 }
712 });
713 }
714
715
716 void printMatch(File file, List lines, int i) {
717 StringBuffer sb = new StringBuffer();
718 if (argResults[RECURSIVE]) sb.write('${file.path}:');
719 if (argResults[LINE_NUMBER]) sb.write('${i + 1}:');
720 sb.write(lines[i]);
721 print(sb.toString());
722 }
723
724 searchFile(File file, searchTerms) {
725 <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) {
726 for (var i = 0; i &lt; lines.length; i++) {
727 bool found = false;
728 for (var j = 0; j &lt; searchTerms.length &amp;&amp; !found; j++) {
729 if (lines[i].contains(searchTerms[j])) {
730 printMatch(file, lines, i);
731 found = true;
732 }
733 }
734 }
735 }).catchError(print);
736 }
737
738 </pre>
739
740 ## Other resources {#other-resources}
741
742 One kind of command-line app that you can write is an HTTP server.
Kathy Walrath 2013/12/20 23:12:16 I'd lead with the link, instead of the discussion.
743 Check out the
744 <a href="https://code.google.com/p/dart/source/browse/branches/bleeding_edge/dar t/samples/dartiverse_search/readme.txt">dartiverse_search</a>
745 example to see a search app that uses HttpServer and WebSockets.
746
747 This tutorial described some basic API found in these classes from the dart:io l ibrary:
Kathy Walrath 2013/12/20 23:12:16 This intro makes this sound like a summary of the
mem 2013/12/30 22:17:13 Done.
748
749 | Class | Description |
Kathy Walrath 2013/12/20 23:12:16 Class -> API?
mem 2013/12/30 22:17:13 Done.
750 |---|---|
751 | <a href="https://api.dartlang.org/dart_io/IOSink.html" target="_blank">IOSink< /a> | Helper class for objects that consume data from streams. |
752 | <a href="https://api.dartlang.org/dart_io/File.html" target="_blank">File</a> | Represents a file on the native file system |
753 | <a href="https://api.dartlang.org/dart_io/Directory.html" target="_blank">Dire ctory</a> | Represents a directory on the native file system |
754 | <a href="https://api.dartlang.org/dart_io/FileSystemEntity.html" target="_blan k">FileSystemEntity</a> | Superclass for File and Directory |
755 | <a href="https://api.dartlang.org/dart_io/Platform.html" target="_blank">Platf orm</a> | Provides information about the machine and operating system |
756 | <a href="https://api.dartlang.org/dart_io.html#stdout" target="_blank">stdout< /a> | The standard output |
757 | <a href="https://api.dartlang.org/dart_io.html#stderr" target="_blank">stderr< /a> | The standard error |
758 | <a href="https://api.dartlang.org/dart_io.html#stdin" target="_blank">stdin</a > | The standard input |
759 | <a href="https://api.dartlang.org/dart_io.html#exitCode" target="_blank">exitC ode</a> | Sets the exit code |
760 | <a href="https://api.dartlang.org/dart_io.html#exit" target="_blank">exit()</a > | Sets the exit code and quits |
761 {: .table }
762
763 In addition, this tutorial covers two classes that help with command-line argume nts:
Kathy Walrath 2013/12/20 23:12:16 This, too, is more "Summary" than "Other resources
mem 2013/12/30 22:17:13 Done.
764
765 | Class | Description |
766 |---|---|
767 | <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. |
768 | <a href="https://api.dartlang.org/args/ArgResults" target="_blank">ArgResults< /a> | The result of parsing raw command line arguments using ArgParser. |
769 {: .table }
770
771 Refer to the API docs for <a href="https://api.dartlang.org/dart_io.html" target ="_blank">dart:io</a>,
Kathy Walrath 2013/12/20 23:12:16 This seems like genuine "Other resources" material
mem 2013/12/30 22:17:13 Done.
772 <a href="https://api.dartlang.org/dart_async.html" target="_blank">dart:async</a >,
773 <a href="https://api.dartlang.org/dart_convert.html" target="_blank">dart:conver t</a>,
774 and the
775 <a href="https://api.dartlang.org/dart_args.html" target="_blank">args</a>
776 package for more classes, functions, and properties.
777
778 ## What next? {#what-next}
779
780 The [Get Input from a Form](/docs/tutorials/forms/) tutorial features a client-s erver example,
781 in which the server is an HttpServer.
Kathy Walrath 2013/12/20 23:12:16 Maybe delete this line, ending the sentence at "ex
mem 2013/12/30 22:17:13 Done.
782 The code for the server, which uses CORS headers and handles
783 POST requests, is explained in detail.
784
785 {% endcapture %}
786
787 {% include tutorial.html %}
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698