编写 dart 命令行程序

dart command-line application

1️⃣ 创建应用

使用 dart create 命令,以 console-full 模板创建一个命令行应用:

1
$ dart create -t console-full cli

该命令会创建一个包含下述信息的 Dart 应用:

  • 一个主要的 Dart 源文件,bin/cli.dart,该文件包含一个顶层 main() 函数。该函数是你应用的入口。
  • 一个额外的 Dart 文件,lib/cli.dart,包含一些功能性的函数方法,这些函数方法将会导入到 cli.dart 文件中。
  • 一个 pubspec 文件,pubspec.yaml,包含应用的元数据,包括应用依赖的 package 信息以及所需的版本等。

2️⃣ 运行应用

使用 dart run 命令在应用的根目录运行 Dart VM:

1
2
3
$ cd cli
$ dart run
Hello world: 42!

3️⃣ 输入输出

stdin, stdout, and stderr.

导入 dart:io

1
import 'dart:io';
  • stdout The standard output

    1
    2
    3
    4
    5
    6
    stdout.write('Hello '); // 不换行
    stdout.writeln('World'); // 换行

    /// 输出
    $ dart run bin/cli.dart
    Hello World!
  • stdin The standard input

    1
    2
    3
    4
    5
    6
    7
    8
    stdout.writeln('Type something:');
    final input = stdin.readLineSync(); // 等待用户输入
    stdout.writeln('Yout typed: $input');

    /// 输出
    Type something:
    Hola
    Yout typed: Hola
  • stderr The standard input

    1
    2
    3
    4
    5
    6
    7
    8
    if (input != 'Hola') {
    stderr.writeln('error: input $input != \'Hola\'');
    }

    Type something:
    Hello
    Yout typed: Hello
    error: input Hello != 'Hola' // stderr

4️⃣ 写入文件

  • 新建文件,写入数据。

    1
    2
    3
    4
    5
    final file = File('text.txt');
    final str = 'The quick brown fox jumps over the lazy dog.';
    await file.writeAsString(str, mode: FileMode.write);

    // 当前文件夹生成 text.txt 文件。
  • 打开文件,写入更多数据。

    1
    2
    3
    4
    5
    final file = File('text.txt').openWrite(mode: FileMode.append);

    file.write('The quick brown fox ');
    file.writeln('jumps over the lazy dog.');
    await file.close();

5️⃣ 文件夹操作

导入 path 库:import 'package:path/path.dart';

1
2
3
4
5
6
7
8
9
10
11
final dir = Directory('lib');
if (!await dir.exists()) {
dir.createSync(); // 新建文件夹
}

final newFilePath = path.joinAll([dir.path, 'cli.dart']); // 使用 path 库 joinAll 拼接路径
stdout.writeln(newFilePath);

final newFile = File(newFilePath).openWrite(mode: FileMode.write);
newFile.writeln('import \'dart:io\';');
newFile.writeln('print(\'Hello World!\');');

6️⃣ 使用 platform 获取环境变量

1
2
3
4
5
final envVarMap = Platform.environment;

print('PWD = ${envVarMap["PWD"]}');
print('LOGNAME = ${envVarMap["LOGNAME"]}');
print('PATH = ${envVarMap["PATH"]}');

7️⃣ 设置 exit codes

1
2
3
4
5
6
7
...

exitCode = 0;

// 0: Success
// 1: Warnings
// 2: Errors

8️⃣ 解析命令行参数

  1. 添加 args 依赖

    1
    2
    3
    4
    // pubspec.yaml

    dependencies:
    args:
  2. 导入

    1
    import 'package:args/args.dart';
  3. 使用 ArgParser 解析

    1
    2
    3
    4
    5
    6
    7
    8
    final parser = ArgParser()..addOption('name', abbr: 'n', help: 'Greeting');
    final argResults = parser.parse(arguments);
    final name = argResults['name'];
    print('Hello $name!');

    // 输出
    $ pub run cli -n World
    Hello World!

9️⃣ 多命令 CommandRunner

  1. 导入

    1
    import 'package:args/command_runner.dart';
  2. 自定义命令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    class GreetingCommand extends Command {
    GreetingCommand() {
    argParser.addOption('name', abbr: 'n', help: 'Greeting');
    }

    @override
    String get name => 'greeting';

    @override
    String get description => '欢迎';

    @override
    void run() {
    final name = argResults['name'];
    print('Hello $name!');
    }
    }
  3. 使用 CommandRunner 添加命令

    1
    2
    3
    4
    5
    6
    7
    void main(List<String> arguments) {
    CommandRunner('cli', 'desc')
    ..addCommand(GreetingCommand())
    ..run(arguments);

    exitCode = 0;
    }
  4. 命令行使用说明 (help)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    // cli 帮助
    $ pub run cli -h
    desc

    Usage: cli <command> [arguments]

    Global options:
    -h, --help Print this usage information.

    Available commands:
    greeting 欢迎

    Run "cli help <command>" for more information about a command.

    // greeting 帮助
    $ pub run cli greeting -h
    欢迎

    Usage: cli greeting [arguments]
    -h, --help Print this usage information.
    -n, --name Greeting

    Run "cli help" to see global options.

🔟 catch error

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void main(List<String> arguments) async {
try {
final runner = CommandRunner<int>('cli', 'desc')
..addCommand(GreetingCommand());
final result = await runner.run(arguments);
exitCode = result;
} catch (e, s) {
if (e is UsageException) {
print(red.wrap(e.message));
print(' ');
print(e.usage);
exitCode = ExitCode.usage.code;
} else {
print(red.wrap(e.toString()));
print(red.wrap(s.toString()));
exitCode = ExitCode.unavailable.code;
}
}
}
1
2
3
4
5
6
7
8
$ pub run cli greeting -n
Missing argument for "name".

Usage: cli greeting [arguments]
-h, --help Print this usage information.
-n, --name Greeting

Run "cli help" to see global options.

参考

pub global 命令

编写命令行应用

起步教程:编写命令行和服务端应用