Dart命令行工具一- 尝试上手开发
前言
已经有很多人开发了一些 dart 命令行工具,并上传到了 pub ,而我会来开发一个命令行工具是我想将一款 ROM 处理工具用 dart 命令行重构,这样能更快的实现跨平台,即使原工具是使用 Flutter 开发,但在适配桌面端的过程中,除了能将 UI 简单的改动能适配到 PC 端后,其中具体功能的业务逻辑适配起来异常的困难,其中包括 windows 终端命令的调用,local pty 的实现等。并且一部分的用户希望能在 Linux 服务器运行我的程序。
上手开发
创建一个 dart 工程
无论是 python 还是 dart,都会有一个 arg 类似的包来提供对命令参数的解析。
mkdir dart_cli && cd dart_cli
touch pubspec.yaml
pubspec.yaml 内容
name: dart_cli
dependencies:
args: ^1.6.0
随后执行pub get
我们再新建一个 bin 文件夹,再在文件夹里面新建 dart_cli.dart。
编写 main 函数
一个 arg 参数解析例子
import 'package:args/args.dart';
void main(List<String> arguments) {
// 创建ArgParser的实例,同时指定需要输入的参数
final ArgParser argParser = new ArgParser()
..addOption('name',
abbr: 'n', defaultsTo: 'World', help: "Who would you like to greet?")
..addFlag('help',
abbr: 'h', negatable: false, help: "Displays this help information.");
ArgResults argResults = argParser.parse(arguments);
if (argResults['help']) {
print("""
** HELP **
${argParser.usage}
""");
}
final String name = argResults['name'];
print("Hello, $name!");
}
addOption 是添加参数解析的规则,abbr 是参数开关的缩写,也就是说 name 这个参数开关,你可以使用 --name Nightmare,也可以使用 -n Nightmare。
执行 pub run dart_cli
或者在 vs code 中右键运行这个 dart_cli.dart。
测试参数
有个 linux 终端小技巧,按上下键可以切换历史命令 执行
pub run dart_cli -n Nightmare
或者pub run dart_cli --name Nightmare
同理pub run dart_cli -h
以上是 dart 开发命令行工具最基础的部分。
进阶
如果我们希望我们的命令行工具不只是简单的接收参数执行命令,如果想让它能够具有交互功能,应该怎么来做呢?
这部分的知识全部归根于对终端模拟器的编写
关闭 dart 开关
stdin.echoMode = false;
stdin.lineMode = false;
第一个开启会将用户的输入打印出来,我们通常只需要获得用户的输入值。
第二个开启后,在用户按下回车前之前,我们拿不到用户的输入。
获取键盘输入
while (true) {
final int input = stdin.readByteSync();
if (input != -1) {
print('input -> $input');
}
await Future<void>.delayed(const Duration(milliseconds: 10));
}
不加延时代码的话,循环会极大占用 CPU。 其中上下左右的按键会涉及到终端转义序列的识别。
如何解析,分享给大家
bool csiStart = false;
bool escStart = false;
while (true) {
final int input = stdin.readByteSync();
if (input != -1) {
if (csiStart) {
csiStart = false;
// print(input);
switch (input) {
case 65:
// up
print('press up');
break;
case 66:
// down
print('press down');
break;
case 68:
// left
print('press left');
break;
case 67:
// right
print('press right');
break;
}
}
if (escStart) {
escStart = false;
if (input == 91) {
csiStart = true;
}
}
if (input == 27) {
escStart = true;
}
}
await Future<void>.delayed(const Duration(milliseconds: 10));
}
在 windows 平台拿不到上下左右的监听,如果有实现方法请在评论区留言。
转换 print
在命令行工具的开发中,我们有时候更希望 print 函数不自动换行。
void print(Object object) {
stdout.write(object);
}
实现交互
先打印类似于这样的文本
1.文件转换
2.动态模块
3.一键执行
引入一个 index 与箭头的打印字符串
int chooseIndex = 1;
const String arrow = ' \x1b[1;32m←\x1b[0m ';
\x1b[1;32m
是将终端当前前景色改为绿色,字体加粗,\x1b[0m
是恢复默认。
引入简单的光标控制方法
const String cursorUpChar = '\x1b[A';
const String cursorDownChar = '\x1b[B';
const String cursorLeftChar = '\x1b[D';
const String cursorRightChar = '\x1b[C';
// 从当前光标的位置删至行的末尾
const String deleteOneChar = '\x1b[0K';
void cursorUp() => print(cursorUpChar);
void cursorDown() => print(cursorDownChar);
void cursorLeft() => print(cursorLeftChar);
void cursorRight() => print(cursorRightChar);
void deleteOne() => print(deleteOneChar);
箭头控制方法
void showArrow() {
for (int i = 3 - chooseIndex; i > 0; i--) {
cursorUp();
}
print(arrowChar);
}
void deleteArrow() {
cursorLeft();
cursorLeft();
cursorLeft();
deleteOne();
}
执行控制箭头
case 65:
if (chooseIndex > 1) {
chooseIndex--;
deleteArrow();
cursorUp();
print(arrowChar);
}
break;
case 66:
if (chooseIndex < 3) {
chooseIndex ;
deleteArrow();
cursorDown();
print(arrowChar);
}
break;
效果
完整代码
import 'dart:io';
const String arrowChar = ' \x1b[1;32m←\x1b[0m ';
const String cursorUpChar = '\x1b[A';
const String cursorDownChar = '\x1b[B';
const String cursorLeftChar = '\x1b[D';
const String cursorRightChar = '\x1b[C';
// 从当前光标的位置删至行的末尾
const String deleteOneChar = '\x1b[0K';
void cursorUp() => print(cursorUpChar);
void cursorDown() => print(cursorDownChar);
void cursorLeft() => print(cursorLeftChar);
void cursorRight() => print(cursorRightChar);
void deleteOne() => print(deleteOneChar);
int chooseIndex = 1;
void showArrow() {
for (int i = 3 - chooseIndex; i > 0; i--) {
cursorUp();
}
print(arrowChar);
}
void deleteArrow() {
cursorLeft();
cursorLeft();
cursorLeft();
deleteOne();
}
Future<void> main(List<String> arguments) async {
stdin.echoMode = false;
stdin.lineMode = false;
bool csiStart = false;
bool escStart = false;
print('1.文件转换\n');
print('2.动态模块\n');
print('3.一键执行');
// cursorLeft();
showArrow();
// 隐藏光标,没有生效
print('\x1b[?25l');
while (true) {
final int input = stdin.readByteSync();
if (input != -1) {
if (csiStart) {
csiStart = false;
// print(input);
switch (input) {
case 65:
if (chooseIndex > 1) {
chooseIndex--;
deleteArrow();
cursorUp();
print(arrowChar);
}
// up
// print('press up');
break;
case 66:
// down
// print('press down');
if (chooseIndex < 3) {
chooseIndex ;
deleteArrow();
cursorDown();
print(arrowChar);
}
break;
case 68:
// left
// print('press left');
break;
case 67:
// right
// print('press right');
break;
}
}
if (escStart) {
escStart = false;
if (input == 91) {
csiStart = true;
}
}
if (input == 27) {
escStart = true;
}
}
await Future<void>.delayed(const Duration(milliseconds: 10));
}
}
void print(Object object) {
stdout.write(object);
}
好了就这样了,目前正在着手这个 dart 命令行工具能复用我当前的 Flutter 项目的 util,比如用户登录等。
任何疑问可以评论区留言。
这篇好文章是转载于:学新通技术网
- 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
- 本站站名: 学新通技术网
- 本文地址: /boutique/detail/tanheggfbh
-
photoshop保存的图片太大微信发不了怎么办
PHP中文网 06-15 -
《学习通》视频自动暂停处理方法
HelloWorld317 07-05 -
word里面弄一个表格后上面的标题会跑到下面怎么办
PHP中文网 06-20 -
Android 11 保存文件到外部存储,并分享文件
Luke 10-12 -
photoshop扩展功能面板显示灰色怎么办
PHP中文网 06-14 -
微信公众号没有声音提示怎么办
PHP中文网 03-31 -
excel下划线不显示怎么办
PHP中文网 06-23 -
excel打印预览压线压字怎么办
PHP中文网 06-22 -
TikTok加速器哪个好免费的TK加速器推荐
TK小达人 10-01 -
怎样阻止微信小程序自动打开
PHP中文网 06-13