From 8e25b2d5f54637e80ea400909dbf6e006c190a14 Mon Sep 17 00:00:00 2001 From: Kevin Moore Date: Thu, 7 May 2026 13:07:59 -0700 Subject: [PATCH] WIP: Trying out excerpts --- pkgs/args/README.md | 92 +++++-- pkgs/args/example/readme_examples.dart | 256 +++++++++++++++++++ pkgs/characters/README.md | 1 + pkgs/characters/example/readme_examples.dart | 30 +++ pkgs/collection/README.md | 6 +- pkgs/collection/example/readme_examples.dart | 16 ++ pkgs/crypto/README.md | 64 ++--- pkgs/crypto/example/readme_examples.dart | 48 ++++ pkgs/logging/README.md | 64 ++--- pkgs/logging/example/readme_examples.dart | 88 +++++++ pkgs/os_detect/README.md | 1 + pkgs/os_detect/example/readme_examples.dart | 10 + pkgs/path/README.md | 3 + pkgs/path/example/readme_examples.dart | 22 ++ pkgs/typed_data/README.md | 1 + pkgs/typed_data/example/readme_examples.dart | 11 + 16 files changed, 620 insertions(+), 93 deletions(-) create mode 100644 pkgs/args/example/readme_examples.dart create mode 100644 pkgs/characters/example/readme_examples.dart create mode 100644 pkgs/collection/example/readme_examples.dart create mode 100644 pkgs/crypto/example/readme_examples.dart create mode 100644 pkgs/logging/example/readme_examples.dart create mode 100644 pkgs/os_detect/example/readme_examples.dart create mode 100644 pkgs/path/example/readme_examples.dart create mode 100644 pkgs/typed_data/example/readme_examples.dart diff --git a/pkgs/args/README.md b/pkgs/args/README.md index b8f5ee2e4..e4b6ccd81 100644 --- a/pkgs/args/README.md +++ b/pkgs/args/README.md @@ -11,16 +11,23 @@ server-side and client-side apps. First create an [ArgParser][]: - var parser = ArgParser(); + +```dart +var parser = ArgParser(); +``` Then define a set of options on that parser using [addOption()][addOption] and [addFlag()][addFlag]. Here's the minimal way to create an option named "name": - parser.addOption('name'); + +```dart +parser.addOption('name'); +``` When an option can only be set or unset (as opposed to taking a string value), use a flag: + ```dart parser.addFlag('name'); ``` @@ -28,6 +35,7 @@ parser.addFlag('name'); Flag options, by default, accept a 'no-' prefix to negate the option. You can disable the 'no-' prefix using the `negatable` parameter: + ```dart parser.addFlag('name', negatable: false); ``` @@ -38,6 +46,7 @@ cases where the distinction matters, we'll use "non-flag option." Options can have an optional single-character abbreviation, specified with the `abbr` parameter: + ```dart parser.addOption('mode', abbr: 'm'); parser.addFlag('verbose', abbr: 'v'); @@ -46,6 +55,7 @@ parser.addFlag('verbose', abbr: 'v'); Options can also have a default value, specified with the `defaultsTo` parameter. The default value is used when arguments don't specify the option. + ```dart parser.addOption('mode', defaultsTo: 'debug'); parser.addFlag('verbose', defaultsTo: false); @@ -59,6 +69,7 @@ allowed set of values. When you do, the parser throws an [`ArgParserException`][ArgParserException] if the value for an option is not in the allowed set. Here's an example of specifying allowed values: + ```dart parser.addOption('mode', allowed: ['debug', 'release']); ``` @@ -67,6 +78,7 @@ You can use the `callback` parameter to associate a function with an option. Later, when parsing occurs, the callback function is invoked with the value of the option: + ```dart parser.addOption('mode', callback: (mode) => print('Got mode $mode')); parser.addFlag('verbose', callback: (verbose) { @@ -81,6 +93,7 @@ value, or `null` if no default value is set. If an option is `mandatory` but not provided, the results object throws an [`ArgumentError`][ArgumentError] on retrieval. + ```dart parser.addOption('mode', mandatory: true); ``` @@ -90,26 +103,32 @@ parser.addOption('mode', mandatory: true); Once you have an [ArgParser][] set up with some options and flags, you use it by calling [ArgParser.parse()][parse] with a set of arguments: + ```dart var results = parser.parse(['some', 'command', 'line', 'args']); ``` These arguments usually come from the arguments to `main()`. For example: - main(List args) { - // ... - var results = parser.parse(args); - } + +```dart +main(List args) { + // ... + var results = parser.parse(args); +} +``` However, you can pass in any list of strings. The `parse()` method returns an instance of [ArgResults][], a map-like object that contains the values of the parsed options. + ```dart var parser = ArgParser(); parser.addOption('mode'); parser.addFlag('verbose', defaultsTo: true); -var results = parser.parse(['--mode', 'debug', 'something', 'else']); +var results = + parser.parse(['--mode', 'debug', 'something', 'else']); print(results.option('mode')); // debug print(results.flag('verbose')); // true @@ -120,6 +139,7 @@ passed after positional parameters unless `--` is used to indicate that all further parameters will be positional. The positional arguments go into [ArgResults.rest][rest]. + ```dart print(results.rest); // ['something', 'else'] ``` @@ -132,6 +152,7 @@ To stop parsing options as soon as a positional argument is found, To actually pass in options and flags on the command line, use GNU or POSIX style. Consider this option: + ```dart parser.addOption('name', abbr: 'n'); ``` @@ -147,6 +168,7 @@ You can specify its value on the command line using any of the following: Consider this flag: + ```dart parser.addFlag('name', abbr: 'n'); ``` @@ -167,6 +189,7 @@ You can set it to false using the following: Multiple flag abbreviations can be collapsed into a single argument. Say you define these flags: + ```dart parser ..addFlag('verbose', abbr: 'v') @@ -183,6 +206,7 @@ You can set all three flags at once: By default, an option has only a single value, with later option values overriding earlier ones; for example: + ```dart var parser = ArgParser(); parser.addOption('mode'); @@ -194,6 +218,7 @@ Multiple values can be parsed with `addMultiOption()`. With this method, an option can occur multiple times, and the `parse()` method returns a list of values: + ```dart var parser = ArgParser(); parser.addMultiOption('mode'); @@ -203,6 +228,7 @@ print(results.multiOption('mode')); // prints '[on, off]' By default, values for a multi-valued option may also be separated with commas: + ```dart var parser = ArgParser(); parser.addMultiOption('mode'); @@ -226,6 +252,7 @@ The executable is `git`, the command is `commit`, and the `-a` option is an option passed to the command. You can add a command using the [addCommand][] method: + ```dart var parser = ArgParser(); var command = parser.addCommand('commit'); @@ -235,6 +262,7 @@ It returns another [ArgParser][], which you can then use to define options specific to that command. If you already have an [ArgParser][] for the command's options, you can pass it in: + ```dart var parser = ArgParser(); var command = ArgParser(); @@ -243,6 +271,7 @@ parser.addCommand('commit', command); The [ArgParser][] for a command can then define options or flags: + ```dart command.addFlag('all', abbr: 'a'); ``` @@ -251,9 +280,10 @@ You can add multiple commands to the same parser so that a user can select one from a range of possible commands. When parsing an argument list, you can then determine which command was entered and what options were provided for it. + ```dart -var results = parser.parse(['commit', '-a']); -print(results.command.name); // "commit" +var results = commandParser.parse(['commit', '-a']); +print(results.command.name); // "commit" print(results.command['all']); // true ``` @@ -261,6 +291,7 @@ Options for a command must appear after the command in the argument list. For example, given the above parser, `"git -a commit"` is *not* valid. The parser tries to find the right-most command that accepts an option. For example: + ```dart var parser = ArgParser(); parser.addFlag('all', abbr: 'a'); @@ -294,9 +325,11 @@ e.g. File `dgit.dart` + ```dart void main(List args) { - var runner = CommandRunner("dgit", "A dart implementation of distributed version control.") + var runner = CommandRunner( + 'dgit', 'A dart implementation of distributed version control.') ..addCommand(CommitCommand()) ..addCommand(StashCommand()) ..run(args); @@ -309,12 +342,15 @@ If the [CommandRunner][] finds a matching command then the [CommandRunner][] cal Commands are defined by extending the [Command][] class. For example: + ```dart class CommitCommand extends Command { // The [name] and [description] properties must be defined by every // subclass. - final name = "commit"; - final description = "Record changes to the repository."; + @override + final name = 'commit'; + @override + final description = 'Record changes to the repository.'; CommitCommand() { // we can add command specific arguments here. @@ -323,10 +359,11 @@ class CommitCommand extends Command { } // [run] may also return a Future. + @override void run() { // [argResults] is set before [run()] is called and contains the flags/options // passed to this command. - print(argResults.flag('all')); + print(argResults?.flag('all')); } } ``` @@ -339,8 +376,10 @@ Add argments directly to the [CommandRunner] to specify global arguments: Adding global arguments + ```dart -var runner = CommandRunner('dgit', "A dart implementation of distributed version control."); +var runner = CommandRunner( + 'dgit', 'A dart implementation of distributed version control.'); // add global flag runner.argParser.addFlag('verbose', abbr: 'v', help: 'increase logging'); ``` @@ -382,9 +421,10 @@ commands. If it encounters an error parsing the arguments or processing a command, it throws a [UsageException][]; your `main()` method should catch these and print them appropriately. For example: + ```dart -runner.run(arguments).catchError((error) { - if (error is! UsageException) throw error; +runner.run(args).catchError((Object error) { + if (error is! UsageException) throw Exception(error.toString()); print(error); exit(64); // Exit code 64 indicates a usage error. }); @@ -398,32 +438,36 @@ when you create your options. To define help text for an entire option, use the `help:` parameter: + ```dart -parser.addOption('mode', help: 'The compiler configuration', - allowed: ['debug', 'release']); +parser.addOption('mode', + help: 'The compiler configuration', allowed: ['debug', 'release']); parser.addFlag('verbose', help: 'Show additional diagnostic info'); ``` For non-flag options, you can also provide a help string for the parameter: + ```dart -parser.addOption('out', help: 'The output path', valueHelp: 'path', +parser.addOption('out', + help: 'The output path', + valueHelp: 'path', allowed: ['debug', 'release']); ``` For non-flag options, you can also provide detailed help for each expected value by using the `allowedHelp:` parameter: + ```dart -parser.addOption('arch', help: 'The architecture to compile for', - allowedHelp: { - 'ia32': 'Intel x86', - 'arm': 'ARM Holding 32-bit chip' - }); +parser.addOption('arch', + help: 'The architecture to compile for', + allowedHelp: {'ia32': 'Intel x86', 'arm': 'ARM Holding 32-bit chip'}); ``` To display the help, use the [usage][usage] getter: + ```dart print(parser.usage); ``` diff --git a/pkgs/args/example/readme_examples.dart b/pkgs/args/example/readme_examples.dart new file mode 100644 index 000000000..dd447b237 --- /dev/null +++ b/pkgs/args/example/readme_examples.dart @@ -0,0 +1,256 @@ +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// This file contains all source code snippets displayed in args/README.md +// so that they can be programmatically updated and validated via excerpter. + +// ignore_for_file: unreachable_from_main, +// ignore_for_file: inference_failure_on_instance_creation +// ignore_for_file: unused_local_variable,unused_element + +import 'dart:io'; +import 'package:args/args.dart'; +import 'package:args/command_runner.dart'; + +void main(List args) { + // #docregion parser-init + var parser = ArgParser(); + // #enddocregion parser-init + + // #docregion parser-add-option + parser.addOption('name'); + // #enddocregion parser-add-option + + // #docregion parser-add-flag + parser.addFlag('name'); + // #enddocregion parser-add-flag + + // #docregion parser-add-flag-no-negatable + parser.addFlag('name', negatable: false); + // #enddocregion parser-add-flag-no-negatable + + // #docregion parser-abbr + parser.addOption('mode', abbr: 'm'); + parser.addFlag('verbose', abbr: 'v'); + // #enddocregion parser-abbr + + // #docregion parser-defaultsTo + parser.addOption('mode', defaultsTo: 'debug'); + parser.addFlag('verbose', defaultsTo: false); + // #enddocregion parser-defaultsTo + + // #docregion parser-allowed + parser.addOption('mode', allowed: ['debug', 'release']); + // #enddocregion parser-allowed + + // #docregion parser-callbacks + parser.addOption('mode', callback: (mode) => print('Got mode $mode')); + parser.addFlag('verbose', callback: (verbose) { + if (verbose) print('Verbose'); + }); + // #enddocregion parser-callbacks + + // #docregion parser-mandatory + parser.addOption('mode', mandatory: true); + // #enddocregion parser-mandatory + + // #docregion parser-parse + var results = parser.parse(['some', 'command', 'line', 'args']); + // #enddocregion parser-parse + + // #docregion parser-results-example + var resultsExampleParser = ArgParser(); + resultsExampleParser.addOption('mode'); + resultsExampleParser.addFlag('verbose', defaultsTo: true); + var resultsExample = + resultsExampleParser.parse(['--mode', 'debug', 'something', 'else']); + + print(resultsExample.option('mode')); // debug + print(resultsExample.flag('verbose')); // true + // #enddocregion parser-results-example + + // #docregion parser-rest + print(resultsExample.rest); // ['something', 'else'] + // #enddocregion parser-rest + + // #docregion parser-spec-option + parser.addOption('name', abbr: 'n'); + // #enddocregion parser-spec-option + + // #docregion parser-spec-flag + parser.addFlag('name', abbr: 'n'); + // #enddocregion parser-spec-flag + + // #docregion parser-multiple-abbr + parser + ..addFlag('verbose', abbr: 'v') + ..addFlag('french', abbr: 'f') + ..addFlag('iambic-pentameter', abbr: 'i'); + // #enddocregion parser-multiple-abbr + + // #docregion parser-override + var overrideParser = ArgParser(); + overrideParser.addOption('mode'); + var overrideResults = overrideParser.parse(['--mode', 'on', '--mode', 'off']); + print(overrideResults.option('mode')); // prints 'off' + // #enddocregion parser-override + + // #docregion parser-multi-option + var multiParser = ArgParser(); + multiParser.addMultiOption('mode'); + var multiResults = multiParser.parse(['--mode', 'on', '--mode', 'off']); + print(multiResults.multiOption('mode')); // prints '[on, off]' + // #enddocregion parser-multi-option + + // #docregion parser-multi-option-commas + var multiCommaParser = ArgParser(); + multiCommaParser.addMultiOption('mode'); + var multiCommaResults = multiCommaParser.parse(['--mode', 'on,off']); + print(multiCommaResults.multiOption('mode')); // prints '[on, off]' + // #enddocregion parser-multi-option-commas + + // #docregion parser-command-init + var commandParser = ArgParser(); + var command = commandParser.addCommand('commit'); + // #enddocregion parser-command-init + + // #docregion parser-command-add + var commandParser2 = ArgParser(); + var command2 = ArgParser(); + commandParser2.addCommand('commit', command2); + // #enddocregion parser-command-add + + // #docregion parser-command-flag + command2.addFlag('all', abbr: 'a'); + // #enddocregion parser-command-flag + + // #docregion parser-command-results + var commandResults = commandParser.parse(['commit', '-a']); + print(commandResults.command?.name); // "commit" + print(commandResults.command?['all']); // true + // #enddocregion parser-command-results + + // #docregion parser-command-ambiguity + var commandAmbiguityParser = ArgParser(); + commandAmbiguityParser.addFlag('all', abbr: 'a'); + var commandAmbiguitySub = commandAmbiguityParser.addCommand('commit'); + commandAmbiguitySub.addFlag('all', abbr: 'a'); + + var commandAmbiguityResults = commandAmbiguityParser.parse(['commit', '-a']); + print(commandAmbiguityResults.command?['all']); // true + // #enddocregion parser-command-ambiguity + + // #docregion parser-usage-example + parser.addOption('mode', + help: 'The compiler configuration', allowed: ['debug', 'release']); + parser.addFlag('verbose', help: 'Show additional diagnostic info'); + // #enddocregion parser-usage-example + + // #docregion parser-usage-out + parser.addOption('out', + help: 'The output path', + valueHelp: 'path', + allowed: ['debug', 'release']); + // #enddocregion parser-usage-out + + // #docregion parser-usage-arch + parser.addOption('arch', + help: 'The architecture to compile for', + allowedHelp: {'ia32': 'Intel x86', 'arm': 'ARM Holding 32-bit chip'}); + // #enddocregion parser-usage-arch + + // #docregion parser-usage-print + print(parser.usage); + // #enddocregion parser-usage-print +} + +// #docregion runner-command +class CommitCommand extends Command { + // The [name] and [description] properties must be defined by every + // subclass. + @override + final name = 'commit'; + @override + final description = 'Record changes to the repository.'; + + CommitCommand() { + // we can add command specific arguments here. + // [argParser] is automatically created by the parent class. + argParser.addFlag('all', abbr: 'a'); + } + + // [run] may also return a Future. + @override + void run() { + // [argResults] is set before [run()] is called and contains the flags/options + // passed to this command. + print(argResults?.flag('all')); + } +} +// #enddocregion runner-command + +class StashCommand extends Command { + @override + final String name = 'stash'; + @override + final String description = 'Stash changes in the working directory.'; + + StashCommand() { + addSubcommand(StashSaveCommand()); + addSubcommand(StashListCommand()); + } +} + +class StashSaveCommand extends Command { + @override + final name = 'save'; + @override + final description = 'Save stash'; + @override + void run() {} +} + +class StashListCommand extends Command { + @override + final name = 'list'; + @override + final description = 'List stash'; + @override + void run() {} +} + +void runnerExample(List args) { + // #docregion runner-main + void main(List args) { + var runner = CommandRunner( + 'dgit', 'A dart implementation of distributed version control.') + ..addCommand(CommitCommand()) + ..addCommand(StashCommand()) + ..run(args); + } + // #enddocregion runner-main + + // #docregion runner-global-args + var runner = CommandRunner( + 'dgit', 'A dart implementation of distributed version control.'); + // add global flag + runner.argParser.addFlag('verbose', abbr: 'v', help: 'increase logging'); + // #enddocregion runner-global-args + + // #docregion runner-run-catch + runner.run(args).catchError((Object error) { + if (error is! UsageException) throw Exception(error.toString()); + print(error); + exit(64); // Exit code 64 indicates a usage error. + }); + // #enddocregion runner-run-catch +} + +// #docregion parser-main-args +void mainExample(List args) { + final parser = ArgParser(); + // ... + var results = parser.parse(args); +} +// #enddocregion parser-main-args diff --git a/pkgs/characters/README.md b/pkgs/characters/README.md index 2bb1f5dcd..177436bcd 100644 --- a/pkgs/characters/README.md +++ b/pkgs/characters/README.md @@ -93,6 +93,7 @@ to move to the next grapheme cluster. Example: + ```dart // Using String indices. String? firstTagString(String source) { diff --git a/pkgs/characters/example/readme_examples.dart b/pkgs/characters/example/readme_examples.dart new file mode 100644 index 000000000..78b919d3e --- /dev/null +++ b/pkgs/characters/example/readme_examples.dart @@ -0,0 +1,30 @@ +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// This file contains the code snippets for characters/README.md. + +import 'package:characters/characters.dart'; + +// #docregion source-index-vs-range +// Using String indices. +String? firstTagString(String source) { + var start = source.indexOf('<') + 1; + if (start > 0) { + var end = source.indexOf('>', start); + if (end >= 0) { + return source.substring(start, end); + } + } + return null; +} + +// Using CharacterRange operations. +Characters? firstTagCharacters(Characters source) { + var range = source.findFirst('<'.characters); + if (range != null && range.moveUntil('>'.characters)) { + return range.currentCharacters; + } + return null; +} +// #enddocregion source-index-vs-range diff --git a/pkgs/collection/README.md b/pkgs/collection/README.md index 8c72c67ec..0b9c97548 100644 --- a/pkgs/collection/README.md +++ b/pkgs/collection/README.md @@ -26,8 +26,12 @@ that considers two sets equal exactly if they contain identical elements. Equalities are provided for `Iterable`s, `List`s, `Set`s, and `Map`s, as well as combinations of these, such as: + ```dart -const MapEquality(IdentityEquality(), ListEquality()); +const MapEquality>( + keys: IdentityEquality(), + values: ListEquality(), +); ``` This equality considers maps equal if they have identical keys, and the diff --git a/pkgs/collection/example/readme_examples.dart b/pkgs/collection/example/readme_examples.dart new file mode 100644 index 000000000..9faa4c92c --- /dev/null +++ b/pkgs/collection/example/readme_examples.dart @@ -0,0 +1,16 @@ +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// This file contains the code snippets for collection/README.md. + +import 'package:collection/collection.dart'; + +void main() { + // #docregion map-equality + const MapEquality>( + keys: IdentityEquality(), + values: ListEquality(), + ); + // #enddocregion map-equality +} diff --git a/pkgs/crypto/README.md b/pkgs/crypto/README.md index d2d0a02c3..b3ad8e3dd 100644 --- a/pkgs/crypto/README.md +++ b/pkgs/crypto/README.md @@ -24,18 +24,14 @@ To hash a list of bytes, invoke the [`convert`][convert] method on the [`sha1`][sha1-obj], [`sha256`][sha256-obj] or [`md5`][md5-obj] objects. + ```dart -import 'package:crypto/crypto.dart'; -import 'dart:convert'; // for the utf8.encode method +var bytes = utf8.encode("foobar"); // data being hashed -void main() { - var bytes = utf8.encode("foobar"); // data being hashed +var digest = sha1.convert(bytes); - var digest = sha1.convert(bytes); - - print("Digest as bytes: ${digest.bytes}"); - print("Digest as hex string: $digest"); -} +print("Digest as bytes: ${digest.bytes}"); +print("Digest as hex string: $digest"); ``` ### Digest on chunked input @@ -49,26 +45,20 @@ method for each chunk of input data, and invoke the `close` method when all the chunks have been added. The digest can then be retrieved from the `Sink` used to create the input data sink. + ```dart -import 'dart:convert'; - -import 'package:convert/convert.dart'; -import 'package:crypto/crypto.dart'; - -void main() { - var firstChunk = utf8.encode("foo"); - var secondChunk = utf8.encode("bar"); - - var output = AccumulatorSink(); - var input = sha1.startChunkedConversion(output); - input.add(firstChunk); - input.add(secondChunk); // call `add` for every chunk of input data - input.close(); - var digest = output.events.single; - - print("Digest as bytes: ${digest.bytes}"); - print("Digest as hex string: $digest"); -} +var firstChunk = utf8.encode("foo"); +var secondChunk = utf8.encode("bar"); + +var output = AccumulatorSink(); +var input = sha1.startChunkedConversion(output); +input.add(firstChunk); +input.add(secondChunk); // call `add` for every chunk of input data +input.close(); +var digest = output.events.single; + +print("Digest as bytes: ${digest.bytes}"); +print("Digest as hex string: $digest"); ``` The above example uses the `AccumulatorSink` class that comes with the @@ -82,20 +72,16 @@ Create an instance of the [`Hmac`][Hmac] class with the hash function and secret key being used. The object can then be used like the other hash calculating objects. + ```dart -import 'dart:convert'; -import 'package:crypto/crypto.dart'; - -void main() { - var key = utf8.encode('p@ssw0rd'); - var bytes = utf8.encode("foobar"); +var key = utf8.encode('p@ssw0rd'); +var bytes = utf8.encode("foobar"); - var hmacSha256 = Hmac(sha256, key); // HMAC-SHA256 - var digest = hmacSha256.convert(bytes); +var hmacSha256 = Hmac(sha256, key); // HMAC-SHA256 +var digest = hmacSha256.convert(bytes); - print("HMAC digest as bytes: ${digest.bytes}"); - print("HMAC digest as hex string: $digest"); -} +print("HMAC digest as bytes: ${digest.bytes}"); +print("HMAC digest as hex string: $digest"); ``` ## Disclaimer diff --git a/pkgs/crypto/example/readme_examples.dart b/pkgs/crypto/example/readme_examples.dart new file mode 100644 index 000000000..7f27a8382 --- /dev/null +++ b/pkgs/crypto/example/readme_examples.dart @@ -0,0 +1,48 @@ +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// This file contains code snippets for crypto/README.md. + +// ignore_for_file: unused_local_variable, prefer_single_quotes + +import 'dart:convert'; +import 'package:convert/convert.dart'; +import 'package:crypto/crypto.dart'; + +void main() { + // #docregion digest-single + var bytes = utf8.encode("foobar"); // data being hashed + + var digest = sha1.convert(bytes); + + print("Digest as bytes: ${digest.bytes}"); + print("Digest as hex string: $digest"); + // #enddocregion digest-single + + // #docregion digest-chunked + var firstChunk = utf8.encode("foo"); + var secondChunk = utf8.encode("bar"); + + var output = AccumulatorSink(); + var input = sha1.startChunkedConversion(output); + input.add(firstChunk); + input.add(secondChunk); // call `add` for every chunk of input data + input.close(); + var chunkedDigest = output.events.single; + + print("Digest as bytes: ${chunkedDigest.bytes}"); + print("Digest as hex string: $chunkedDigest"); + // #enddocregion digest-chunked + + // #docregion digest-hmac + var key = utf8.encode('p@ssw0rd'); + var hmacBytes = utf8.encode("foobar"); + + var hmacSha256 = Hmac(sha256, key); // HMAC-SHA256 + var hmacDigest = hmacSha256.convert(hmacBytes); + + print("HMAC digest as bytes: ${hmacDigest.bytes}"); + print("HMAC digest as hex string: $hmacDigest"); + // #enddocregion digest-hmac +} diff --git a/pkgs/logging/README.md b/pkgs/logging/README.md index 662314500..5080ad9c8 100644 --- a/pkgs/logging/README.md +++ b/pkgs/logging/README.md @@ -10,6 +10,7 @@ messages. Here is a simple logging configuration that logs all messages via `print`. + ```dart Logger.root.level = Level.ALL; // defaults to Level.INFO Logger.root.onRecord.listen((record) { @@ -35,6 +36,7 @@ class has various properties for the message, error, logger name, and more. To listen for changed level notifications use: + ```dart Logger.root.onLevelChanged.listen((level) { print('The new log level is $level'); @@ -46,12 +48,14 @@ Logger.root.onLevelChanged.listen((level) { Create a `Logger` with a unique name to easily identify the source of the log messages. + ```dart final log = Logger('MyClassName'); ``` Here is an example of logging a debug message and an error: + ```dart var future = doSomethingAsync().then((result) { log.fine('Got the result: $result'); @@ -62,6 +66,7 @@ var future = doSomethingAsync().then((result) { When logging more complex messages, you can pass a closure instead that will be evaluated only if the message is actually logged: + ```dart log.fine(() => [1, 2, 3, 4, 5].map((e) => e * 4).join("-")); ``` @@ -88,45 +93,46 @@ Then, create unique loggers and configure their `level` attributes and assign an their `onRecord` streams. + ```dart - hierarchicalLoggingEnabled = true; - Logger.root.level = Level.WARNING; - Logger.root.onRecord.listen((record) { - print('[ROOT][WARNING+] ${record.message}'); - }); +hierarchicalLoggingEnabled = true; +Logger.root.level = Level.WARNING; +Logger.root.onRecord.listen((record) { + print('[ROOT][WARNING+] ${record.message}'); +}); - final log1 = Logger('FINE+'); - log1.level = Level.FINE; - log1.onRecord.listen((record) { - print('[LOG1][FINE+] ${record.message}'); - }); +final log1 = Logger('FINE+'); +log1.level = Level.FINE; +log1.onRecord.listen((record) { + print('[LOG1][FINE+] ${record.message}'); +}); - // log2 inherits LEVEL value of WARNING from `Logger.root` - final log2 = Logger('WARNING+'); - log2.onRecord.listen((record) { - print('[LOG2][WARNING+] ${record.message}'); - }); +// log2 inherits LEVEL value of WARNING from `Logger.root` +final log2 = Logger('WARNING+'); +log2.onRecord.listen((record) { + print('[LOG2][WARNING+] ${record.message}'); +}); - // Will NOT print because FINER is too low level for `Logger.root`. - log1.finer('LOG_01 FINER (X)'); +// Will NOT print because FINER is too low level for `Logger.root`. +log1.finer('LOG_01 FINER (X)'); - // Will print twice ([LOG1] & [ROOT]) - log1.fine('LOG_01 FINE (√√)'); +// Will print twice ([LOG1] & [ROOT]) +log1.fine('LOG_01 FINE (√√)'); - // Will print ONCE because `log1` only uses root listener. - log1.warning('LOG_01 WARNING (√)'); +// Will print ONCE because `log1` only uses root listener. +log1.warning('LOG_01 WARNING (√)'); - // Will never print because FINE is too low level. - log2.fine('LOG_02 FINE (X)'); +// Will never print because FINE is too low level. +log2.fine('LOG_02 FINE (X)'); - // Will print twice ([LOG2] & [ROOT]) because warning is sufficient for all - // loggers' levels. - log2.warning('LOG_02 WARNING (√√)'); +// Will print twice ([LOG2] & [ROOT]) because warning is sufficient for all +// loggers' levels. +log2.warning('LOG_02 WARNING (√√)'); - // Will never print because `info` is filtered by `Logger.root.level` of - // `Level.WARNING`. - log2.info('INFO (X)'); +// Will never print because `info` is filtered by `Logger.root.level` of +// `Level.WARNING`. +log2.info('INFO (X)'); ``` Results in: diff --git a/pkgs/logging/example/readme_examples.dart b/pkgs/logging/example/readme_examples.dart new file mode 100644 index 000000000..043704c61 --- /dev/null +++ b/pkgs/logging/example/readme_examples.dart @@ -0,0 +1,88 @@ +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// This file contains code snippets for logging/README.md. + +// ignore_for_file: unused_local_variable, invalid_return_type_for_catch_error +// ignore_for_file: unreachable_from_main, prefer_final_locals, lines_longer_than_80_chars, prefer_single_quotes + +import 'package:logging/logging.dart'; + +void main() { + // #docregion init-root + Logger.root.level = Level.ALL; // defaults to Level.INFO + Logger.root.onRecord.listen((record) { + print('${record.level.name}: ${record.time}: ${record.message}'); + }); + // #enddocregion init-root + + // #docregion on-level-changed + Logger.root.onLevelChanged.listen((level) { + print('The new log level is $level'); + }); + // #enddocregion on-level-changed + + // #docregion create-logger + final log = Logger('MyClassName'); + // #enddocregion create-logger + + // #docregion complex-message + log.fine(() => [1, 2, 3, 4, 5].map((e) => e * 4).join("-")); + // #enddocregion complex-message +} + +Future doSomethingAsync() async {} +dynamic processResult(dynamic result) {} + +void logError(Logger log) { + // #docregion log-error + var future = doSomethingAsync().then((result) { + log.fine('Got the result: $result'); + processResult(result); + }).catchError((Object e, StackTrace stackTrace) => + log.severe('Oh noes!', e, stackTrace)); + // #enddocregion log-error +} + +void setupHierarchical() { + // #docregion hierarchical + hierarchicalLoggingEnabled = true; + Logger.root.level = Level.WARNING; + Logger.root.onRecord.listen((record) { + print('[ROOT][WARNING+] ${record.message}'); + }); + + final log1 = Logger('FINE+'); + log1.level = Level.FINE; + log1.onRecord.listen((record) { + print('[LOG1][FINE+] ${record.message}'); + }); + + // log2 inherits LEVEL value of WARNING from `Logger.root` + final log2 = Logger('WARNING+'); + log2.onRecord.listen((record) { + print('[LOG2][WARNING+] ${record.message}'); + }); + + // Will NOT print because FINER is too low level for `Logger.root`. + log1.finer('LOG_01 FINER (X)'); + + // Will print twice ([LOG1] & [ROOT]) + log1.fine('LOG_01 FINE (√√)'); + + // Will print ONCE because `log1` only uses root listener. + log1.warning('LOG_01 WARNING (√)'); + + // Will never print because FINE is too low level. + log2.fine('LOG_02 FINE (X)'); + + // Will print twice ([LOG2] & [ROOT]) because warning is sufficient for all + // loggers' levels. + log2.warning('LOG_02 WARNING (√√)'); + + // Will never print because `info` is filtered by `Logger.root.level` of + // `Level.WARNING`. + log2.info('INFO (X)'); + // #enddocregion hierarchical +} diff --git a/pkgs/os_detect/README.md b/pkgs/os_detect/README.md index cb931b15c..d134b9e17 100644 --- a/pkgs/os_detect/README.md +++ b/pkgs/os_detect/README.md @@ -14,6 +14,7 @@ getters like `isLinux`, `isAndroid` and `isBrowser` based on the To use this package instead of `dart:io`, replace the import of `dart:io` with: + ```dart import 'package:os_detect/os_detect.dart' as os_detect; ``` diff --git a/pkgs/os_detect/example/readme_examples.dart b/pkgs/os_detect/example/readme_examples.dart new file mode 100644 index 000000000..5230f6ac0 --- /dev/null +++ b/pkgs/os_detect/example/readme_examples.dart @@ -0,0 +1,10 @@ +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// This file contains the code snippets for os_detect/README.md. + +// #docregion import +// ignore: unused_import +import 'package:os_detect/os_detect.dart' as os_detect; +// #enddocregion import diff --git a/pkgs/path/README.md b/pkgs/path/README.md index 53ec88910..55c463c6d 100644 --- a/pkgs/path/README.md +++ b/pkgs/path/README.md @@ -20,6 +20,7 @@ construct a [`p.Context`][Context] for that style. The path library was designed to be imported with a prefix, though you don't have to if you don't want to: + ```dart import 'package:path/path.dart' as p; ``` @@ -28,6 +29,7 @@ The most common way to use the library is through the top-level functions. These manipulate path strings based on your current working directory and the path style (POSIX, Windows, or URLs) of the host platform. For example: + ```dart p.join('directory', 'file.txt'); ``` @@ -38,6 +40,7 @@ This calls the top-level `join()` function to join the "directory" and If you want to work with paths for a specific platform regardless of the underlying platform that the program is running on, you can create a [Context] and give it an explicit [Style]: + ```dart var context = p.Context(style: Style.windows); context.join('directory', 'file.txt'); diff --git a/pkgs/path/example/readme_examples.dart b/pkgs/path/example/readme_examples.dart new file mode 100644 index 000000000..b024de482 --- /dev/null +++ b/pkgs/path/example/readme_examples.dart @@ -0,0 +1,22 @@ +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// This file contains the code snippets for path/README.md. + +// ignore_for_file: unused_import, unused_local_variable, prefer_final_locals + +// #docregion import +import 'package:path/path.dart' as p; +// #enddocregion import + +void main() { + // #docregion join + p.join('directory', 'file.txt'); + // #enddocregion join + + // #docregion context + var context = p.Context(style: p.Style.windows); + context.join('directory', 'file.txt'); + // #enddocregion context +} diff --git a/pkgs/typed_data/README.md b/pkgs/typed_data/README.md index 512f43bb1..2fd3a5275 100644 --- a/pkgs/typed_data/README.md +++ b/pkgs/typed_data/README.md @@ -10,6 +10,7 @@ The `typed_data` package contains utility functions and classes that makes worki The `typed_data` package can be imported using: + ```dart import 'package:typed_data/typed_data.dart'; ``` diff --git a/pkgs/typed_data/example/readme_examples.dart b/pkgs/typed_data/example/readme_examples.dart new file mode 100644 index 000000000..27ac82b5e --- /dev/null +++ b/pkgs/typed_data/example/readme_examples.dart @@ -0,0 +1,11 @@ +// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file +// for details. All rights reserved. Use of this source code is governed by a +// BSD-style license that can be found in the LICENSE file. + +// This file contains the code snippets for typed_data/README.md. + +// ignore_for_file: unused_import + +// #docregion import +import 'package:typed_data/typed_data.dart'; +// #enddocregion import