Flutter for OpenHarmony:completion 打造极速命令行体验(为你的 CLI 工具添加自动补全) 深度解析与鸿蒙适配指南
欢迎加入开源鸿蒙跨平台社区:https://openharmonycrossplatform.ZEEKLOG.net
前言
如果你为鸿蒙开发了一套 CLI 工具(比如 ohos_deploy),用户在终端输入命令时,如果能像 git 或 kubectl 那样按下 <TAB> 键就自动补全参数,体验将会有质的飞跃。
completion 是 Dart 官方提供的一个小巧库,专门用于为 Dart 编写的命令行程序生成 Shell 自动补全脚本(支持 Bash/Zsh)。
对于 OpenHarmony 开发者,这意味着你可以用 Dart 编写出专业级的开发辅助工具,分发给团队使用,极大提升内部开发效率。
一、核心原理
自动补全的原理并非魔法。
- 安装阶段:生成一段 Shell 脚本(如
.bash_completion),告诉 Shell 当用户输入my_cli <TAB>时,去调用my_cli completion ...获取建议。 - 运行阶段:你的程序接收到特殊的 completion 参数,计算当前光标位置的候选词,输出给 Shell。
你的 Dart CLIZsh/Bash用户 (Terminal)你的 Dart CLIZsh/Bash用户 (Terminal)输入 "ohos_cli dep<TAB>"运行 "ohos_cli completion --word='dep'"匹配候选词 (deploy, dependency)返回 "deploy\ndependency"显示补全列表
二、OpenHarmony 适配说明
completion 库运行在宿主机的 Shell 环境中(Mac/Linux/Windows)。
当然,如果你在鸿蒙设备上通过 Termux 或 Shell 环境运行 Dart 程序,只要 Shell 支持(鸿蒙自带的 shell 较为精简,可能不支持高级补全),它也能工作。
主要场景:
它是为鸿蒙工具链开发者准备的。你的工具运行在 PC 上,辅佐鸿蒙开发。
三、基础用例
3.1 定义补全逻辑
import'package:args/args.dart';import'package:completion/completion.dart';voidmain(List<String> args){final parser =ArgParser(); parser.addOption('target', allowed:['android','ios','ohos']);// 1. 尝试处理补全请求// 如果当前是补全模式,tryArgsCompletion 会直接打印建议并退出程序// 否则返回正常的 argstryArgsCompletion(args, parser);// 2. 正常的业务逻辑final results = parser.parse(args);print('正在构建目标: ${results['target']}');}
3.2 安装补全脚本
用户在使用你的工具前,需要运行一次安装命令(只需一次)。
该库并没有自动安装功能,通常你需要提示用户配置 .zshrc 或 .bashrc。
生成的补全脚本通常长这样:
# 自动生成的 setupiftype complete &>/dev/null;then_my_cli_completion(){localsi="$IFS"IFS=$'\n'COMPREPLY=($(COMP_CWORD="$COMP_CWORD"\COMP_LINE="$COMP_LINE"\COMP_POINT="$COMP_POINT"\ my_cli completion -- "${COMP_WORDS[@]}"\2>/dev/null))||return$?IFS="$si"} complete -F _my_cli_completion my_cli fi四、完整实战示例:鸿蒙多模块构建工具
假设你管理着一个包含 50 个 HAP 模块的超大鸿蒙项目,你写了一个工具来单独构建指定的模块。
import'dart:io';import'package:args/args.dart';import'package:completion/completion.dart';voidmain(List<String> args){final parser =ArgParser();// 动态获取所有模块名作为补全候选List<String>getModuleNames(){// 假设当前目录下所有以 feature_ 开头的文件夹都是模块final dir =Directory.current;if(!dir.existsSync())return[];return dir.listSync().whereType<Directory>().map((d)=> d.path.split(Platform.pathSeparator).last).where((name)=> name.startsWith('feature_')).toList();} parser.addCommand('build'); parser.addCommand('clean'); parser.addOption('module', help:'指定模块名');// 拦截补全请求// 注意:tryArgsCompletion 默认只处理静态 allowed 列表// 如果需要动态补全(如扫描文件夹),需要自定义 completion 逻辑(略高级,本库提供基础支持)// 这里演示最基础的静态补全tryArgsCompletion(args, parser);// 业务逻辑var results = parser.parse(args);if(results.command?.name =='build'){print('🔨 正在构建模块: ${results['module'] ?? 'ALL'}');}}
五、总结
completion 是那种“一旦拥有,别无所求”的功能。
虽然它不直接运行在鸿蒙 App 里,但它是提升鸿蒙开发体验的重要一环。如果你致力于打造一套让开发者爱不释手的鸿蒙工具链,请务必为你的 CLI 加上自动补全功能。