深化解析Clap命令行解析库-Rust脚手架 (深入解析)
有感而发
最近,在和前端小同伴聊天发现,在2024年,她们都有计划入局学习的行列。毕竟前端如今太卷了,框架算是走到「走投无路」了,无非就是在原有基础上修修补补。一切他们想在新的赛道弯道超车。然而,苦于各种要素,迟迟找不到入门之法。
确实如她们所言,Rust由于学习门路比拟峻峭,加之和前端言语可以说是交加很少。而后,给大家一种学了马上就会遗记的觉得。并且,由于如今Rust在前端畛域的运行少之又少。除了字节跳动的Rspack,还有Vivo的VivoBlueOS(咱们在外货之光?用Rust编写的VivoBlueOS有过引见),就很少据说其余国际互联网公司无关系的产品和运行。
相比国外,咱们的路线还任重而道远。像国外很多耳熟能详的公司都早已规划Rust开发。最显著的就是,它曾经将只能在桌面运转的PS搬入了阅读器上。(这个咱们也在之前的师夷长技以制夷:跟着PS学前端技术中有过关系引见)
不过,从最新的招聘网站中搜查Rust关系岗位,相比前几年有了很好的改观。并且很多岗位都和前端关系。这说明,Rust在国际曾经有了自己的市场,也象征着在前端畛域也有了一席之地。那么作为职业前端,不想在红海中继续卷,那势必就须要选用蓝海,方可在千军万马之中,杀出一条黑暗之路。
其实,像我在学习Rust也遇到很她们一样的困境。常识点看了,也了解了。然而隔断时期就会遗记。循环往返,就会对这门言语发生一种顺从感。毕竟,编程也算是一种技术工种,唯手熟尔。
前面,我就转变思绪,那就是入手做一些自己以为可以处置前端痛点的事。哪怕做这个事情,其余言语也可以胜任,然而为什么咱们不做更进一步的尝试呢。现阶段,Rust在前端赋能的场景,大局部都是提高编译效率方向。像Rspack[1]/OXC[2]。
既然,慷慨向曾经定了,而后就有了咱们新的尝试。从那开局,就有了咱们上方的尝试方向
就是基于上方的始终试错和尝试,到如今咱们曾经有了像f_cli[3]的npm包,并且曾经部署到公司私库,并投入消费开发了。
同时,在最近的名目开发中,还应用Rust编写WebAssembly启动前端性能的处置。这块等无时机写一篇关系的文章。
前言
耽误了大家几分钟的时期,在上方干脆了半天,其实就是想传播一个思维。Rust其实无法怕,可怕的是学了然而你没用到上班中。就是想着法都要让它贴切上班,运行于上班。
咱们回到正题,其实Rust赋能前端这个方向我也在探索,而后现阶段自我觉得能用到前端名目中的无非就两点
大家不论是从哪个方面失掉Rust常识点,想必大家尝试的第一个Rust运行就是Cli了。
那咱们当天就来聊聊在Rust开发Cli时的神器-clap[4]。
当天,咱们只需是讲关系的概念,针对如何用Rust构建一个CLI,可以翻看咱们之前的文章。
好了,天不早了,干点正事哇。
咱们能所学到的常识点
1.名目初始化
首先,让咱们经过运转以下命令来初始化咱们的名目:cargoinitclap_demo。随后咱们再性能一下名目的基础信息。(description等)
[package]name="clap_demo"version="0.1.0"edition="2021"description="front789带你学习clap"
咱们可以经过运转以下命令将clap减少到咱们的程序中:
cargoaddclap-Fderive
这样在Cargo.toml中的[dependencies]中就有了关系的信息。
[dependencies]clap={version="4.5.1",features=["derive"]}
其中-F示意,咱们只须要clap中的derive特性。
图片
上述流程中,咱们经常使用的clap的版本是最新版,有些和大家用过的语法有区别的话,须要大家鉴别。
这里多说一嘴,假设对前端开发相熟的同窗是不是觉失掉上述流程很相熟。当咱们创立一个前端名目时,是不是会遇到上方的步骤。
npminityarnaddxx
名目成功
和前端开发相似,当咱们把包下载到本地后,咱们就须要在对应的入口文件中引入并口头。在前端开发中咱们普通筛选的是名目根目录下的index.js。而关于Rust名目来讲,它的入口文件是src/mn.rs。(作为二进制名目(BinaryProjects)而言)
useclap::Parser;#[derive(Parser)]#[command(version,about)]structCli{name:String}fnmain(){letcli=Cli::parse();println!("Hello,{}!",cli.name);}
咱们来繁难解释一下上方的代码。
在前端开发中咱们普通经常使用import/require启动第三方库的引入,而在Rust中咱们经常使用use来导入第三方库clap中的Parsertrait。也就是说,经过usexx咱们就可以经常使用clap中的特定性能。也就是把对应的性能引入到该作用域内。
定义了一个结构体,它经常使用clap::Parser的derive宏和command宏,并且只接受一个参数,即name。
#[derive(Parser)]/#[command(version,about)]不是Rust内置的宏,它们是由clap库自定义的环节宏(proceduralros)。
Rust有两种类型的宏:
这些是Rust内置的,经常使用macro_rules定义,例如vec!、println!等。
它们重要用于元编程(metaprogramming),在编译期口头代码生成。
#[derive(Parser)]它经常使用derive属性来智能为Cli结构体成功Parsertrait。这象征着Cli结构体将取得解析命令行参数的性能,而无需手动成功Parsertrait。
图片
#[command(version,about)]用于性能命令行运行程序的元数据。
最后,咱们可以经过cargorun----help来检查对应的信息。
图片
总的来说,这段代码经常使用clap库定义了一个命令行运行程序,它接受一个名为name的字符串参数。当运转这个运行程序时,它会打印出"Hello,{name}"。#[derive(Parser)]和#[command(...)]这两个属性区分用于智能成功Parsertrait和性能运行程序的元数据。
当咱们加载程序并经常使用Cli::parse()时,它将从std::env::args中失掉参数(这个概念咱们之前在环境变量:相熟的生疏人有过引见)。
当然,假构想让咱们的程序愈增强健,咱们可以给name设定一个自动值,这样在没有提供参数的状况下,也能正当运转。
#[derive(Parser,Debug)]#[command(version,about)]structCli{#[arg(default_value="front789")]name:String}
如今,尝试仅经常使用cargorun而不减少其余任何物品,它应该会打印出Hello,front789!。
图片
当然,咱们也可以像在f_cli中一样为参数减少更多的性能,来增强咱们的Cli。
图片
假构想了解更多关于参数性能,可以翻看clap_command-attributes[5]
![Rust脚手架](https://tyye.cn/zb_users/theme/tpure/style/images/lazyload.png)
图片
2.编写子命令
作为一特性能弱小的CLI,咱们有时刻须要经过定义一些子命令来让咱们的目的愈加明白。
假设大家用过咱们的f_cli,那就心照不宣了。
下图是咱们f_cli的依据用户提供的参数,自动构建前端名目的命令。
图片
在f_cli的成功中,咱们就用到了子命令的操作。
图片
上方咱们来繁难成功一个领有子命令的cli。在之前代码的基础上,咱们只须要将刚才结构体中再新增一个参数-command并且其类型为成功sumcommadtrait的枚举
useclap::{Parser,Subcommand};#[derive(Parser,Debug)]#[command(version,about)]structCli{#[arg(default_value="front789")]name:String,#[command(subcommand)]command:Commands}#[derive(Subcommand,Debug,Clone)]enumCommands{Create,Replace,Update,Delete}fnmain(){letcli=Cli::parse();println!("Hello,{:?}!",cli);}
这样,咱们就在上方的基础上领有了一组子命令(CRUD)。这样咱们就可以在cli中调用对应的子命令而后口头对应的操作了。
图片
3.减少命令标记
咱们可以继续丰盛咱们子命令。上方的咱们不是经过一个枚举Commands够了一个组件命令(Create/Replace/Update/Delete)吗。
有时刻,在某一个子命令下,还须要搜集更多的用户选用。那么咱们就可以将枚举中的值关联成一个「匿名结构体」。这样,咱们就可以针对某个子命令做更深的操作了。
还是举咱们之前的f_cli的例子,在咱们经过f_clicreatexxx构建名目时,咱们可以经过-x来像CLI传递Create所用到的必要信息。
图片
useclap::{Parser,Subcommand};#[derive(Parser,Debug)]#[command(version,about)]structCli{#[arg(default_value="front789")]name:String,#[command(subcommand)]command:Commands}#[derive(Subcommand,Debug,Clone)]enumCommands{Create{#[arg(default_value="front789")]name:String,#[arg(default_value="山西")]address:String,},Replace,Update,Delete}
这样咱们就对Create进一步处置,并且在create的时刻,它会从命令行中寻觅对应的name/address信息,并且搜集到clap实例中。
随后,咱们就可以在主函数中经过match来婚配枚举信息,而后口头相对应的操作。
Rust中的婚配是穷举式的:必定穷举到最后的或者性来使代码有效
为了浪费代码量,咱们经过_占位符来处置其余的逻辑。
fnmain(){letcli=Cli::parse();matchcli.command{Commands::Create{name,address}=>{println!("我是{},来自:{}",name,address);},_=>(),}}
当咱们运转cargoruncreate时,由于咱们提供了自动值,在控制台就会输入对应的信息。当然,咱们也可以经过--namexx--addressxx来启动操作。
有人会觉得输入较长的子命令不是很友好,咱们可以经过short='n'来为子命令提供一一般名。同时咱们还可以经过help="xxx"设置对应在--help时,提供应用户的协助信息。
图片
对应的代码如下:
#[derive(Subcommand,Debug,Clone)]enumCommands{Create{#[arg(short='n',lnotallow="name",help="用户信息",default_value="front789")]name:String,#[arg(short='a',lnotallow="address",help="地址信息",requires="name",default_value="山西")]address:String,},Replace,Update,Delete}
4.交互式cli
在上一节中咱们经过对CLI枚举启动变革,让其能够领有了子命令的性能。其实到这步曾经能够失掉到cli中用户输入的值,并且能够启动下一步的操作了。
然而呢,你是一个如虎添翼的人。孤陋寡闻的你突然有一个想法,为什么不能像vite/create/next一样。在触发对应的构建和降级操作后,有一个「人机交互」的环节。而后,用户可以依据自己的喜好来选用咱们cli的内置性能。这样是不是显的愈加友好。
像咱们的f_cli就是这种交互流程。用户经过人机交互的形式可以选用内置性能。
图片
f_cli选用UI库
那咱们就再次用一个繁难的例子来引见一下哇。
装置新的包
首先,咱们须要装置几个用于交互的包。
cargoaddanyhowcargoadddialoguercargoaddconsole
随后,就他们就会智能被注入到Cargo.toml中了。关于anyhow/dialoguer/console咱们就不在这里过多引见了。大家感兴味可以去对应的官方查找.
如今,咱们须要在src/main.rs中引入关系的性能,同时咱们在处置cli变量的时刻,用的是枚举值,所以咱们须要引入clap中针对这类的操作。
useclap::{+builder::EnumValueParser,Parser,Subcommand,+ValueEnum};+usedialoguer::{+console::Term,+theme::ColorfulTheme,+Select+};+useconsole::style;
新增枚举信息
前面说过,咱们想经过人机交互的形式,在cli运转环节中让用户自己选用咱们内置的性能点。所以,这些内置性能咱们可以须要事前设定好。
#[derive(Clone,Copy,Debug,PartialEq,Eq,ValueEnum)]pubenumName{N1,N2,}#[derive(Clone,Copy,Debug,PartialEq,Eq,ValueEnum)]pubenumAddress{A1,A2}
处置结构体中参数的自动值
既然,曾经有了对应的自动值,那么咱们就须要限度咱们cli中的参数必定是这些内置参数中值。
#[derive(Subcommand,Debug,Clone)]enumCommands{Create{#[arg(short='n',lnotallow="name",help="用户信息",+value_parser=EnumValueParser::<Name>::new(),ignore_case=true)]+name:Option<Name>,#[arg(short='a',lnotallow="address",help="地址信息",requires="name",+value_parser=EnumValueParser::<Address>::new(),)]+address:Option<Address>,}}
上方的性能,见名知意,就是从对应的枚举中解析对应的值。
主函数
其实,这步的操作和之前是差不多的,咱们还是应用match对cli.command启动婚配处置。不过咱们这里又进一步的做了容错处置。
由于,在启动操作中咱们会有失误抛出,所以咱们对main的前往值也做了处置。(anyhow::Result<()>)
operation_params
在main中咱们经过match是可以失掉到cli中参数的,而此时咱们还须要依据参数做进一步的处置。咱们把这个逻辑提取到了一个函数中了。
fnoperation_params(name:Option<Name>,address:Option<Address>)->anyhow::Result<()>{letn=matchname{Some(na)=>na,None=>{multiselect_msg("选用一个姓名:");message("经常使用上/下箭头启动选用,经常使用空格或回车键确认。");letitems=vec!["张三","王五"];letselection=Select::with_theme(&ColorfulTheme::default()).items(&items).default(0).interact_on_opt(&Term::stderr())?;matchselection{Some(0)=>Name::N1,Some(1)=>Name::N2,_=>panic!("Fatal:用户信息制订失误."),}}};leta=matchaddress{Some(na)=>na,None=>{multiselect_msg("选用一个地址:");message("经常使用上/下箭头启动选用,经常使用空格或回车键确认。");letitems=vec!["太原","晋中"];letselection=Select::with_theme(&ColorfulTheme::default()).items(&items).default(0).interact_on_opt(&Term::stderr())?;matchselection{Some(0)=>Address::A1,Some(1)=>Address::A2,_=>panic!("Fatal:地址信息制订失误."),}}};println!("name:{:?},地址:{:?}",n,a);Ok(())}
其实上方的逻辑也是比拟繁难明了的。咱们接纳cli中的参数name/address。由于他们都是枚举类型,所以咱们继续用match启动对应值的婚配。
只管,咱们对两个枚举值都做了处置,然而他们的逻辑都是相反的。
上方的逻辑就是当咱们运转子命令时刻
图片
这样,不论咱们上方那种状况,咱们最后都可以拿到对应的值。这样咱们繁难咱们前期启动其余操作。
5.其余有用的库
上方咱们经过几个例子,讲了很多clap的运行例子,其中咱们还配合dialoguer启动人机交互的处置。假设咱们想成功性能愈加弱小的cli咱们还可以借助其余的工具。上方咱们就来繁难引见几种。
crossterm[9]是一款跨终端的crate。它具备各种很酷的性能,如能够更改背景和文本色彩、操作终端自身和光标,以及捕捉键盘和其余事情。
图片
comfy-table
comfy-table[10]是一个设计用于在终端中创立美丽表格的crate。
以下是其官方的案例。用仅仅几句话就可以成功一个在终端展现的表格。
usecomfy_table::Table;fnmain(){letmuttable=Table::new();table.set_header(vec!["Header1","Header2","Header3"]).add_row(vec!["Thisisatext","Thisisanothertext","Thisisthethirdtext",]).add_row(vec!["Thisisanothertext","Nownaddsomenmultilinestuff","Thisisawesome",]);println!("{table}");}
口头后的成果如下:
+----------------------+----------------------+------------------------+|Header1|Header2|Header3|+======================================================================+|Thisisatext|Thisisanothertext|Thisisthethirdtext||----------------------+----------------------+------------------------||Thisisanothertext|Now|Thisisawesome|||addsome||||multilinestuff||+----------------------+----------------------+------------------------+
inquire[11]是一个用于构建终端上交互式揭示的crate。它允许单选、多选、选用日历等性能:
上方的动图是其官方的案例。其中最吸引我的就是那个多选。哈哈。
图片
rust bucket怎么玩 锈桶战士攻略大全
锈桶战士攻略,锈桶战士(rust bucket)是一款好玩的回合制的地牢探险类游戏,本文是游戏的通关图文攻略,有兴趣的玩家可以来看看。 《铁锈水桶》(Rust Bucket)是由 Nitrome 开发的一款像素风动作新游,本作将要开启 Roguelike 玩法,为游戏带来不一样的体验。 《铁锈水桶》的画面依旧继承了 Nitrome 游戏的色彩斑斓特点以及浓厚的像素风格,游戏将会采用回合制,再结合 Roguelike 元素,玩家每当行动一次,敌人就会随机行动一次,这无疑给玩家带来些许压迫感。
RUST1170新版,登陆不了管理员,有谁知道怎么回事?
① 电脑用户有时候设置了密码,自己也忘了,面对操作系统需要密码登陆的界面束手无策。 如此时并不是系统默认的管理员账户Administrator,而是用户自定义的账户(如abc)那么重启电脑,启动到系统登录界面时,同时按住Ctrl+Alt键,然后连击Del键两次,会出现新的登陆界面,在用户名处输入Administrator 密码为空回车即可登陆操作系统进入我们熟悉的桌面了。 进去之后再到控制面板→用户账户abc账户中将密码修改一下即可。 ②第一招不行?还可以重启计算机,在启动画面出现后马上按下F8键,等到安全模式的界面出现之后。 使用键盘上的上、下键选择“带命令行的安全模式”回车执行。 再等到系统加载运行结束后,就会出现超级用户“administrator”和本地用户“abc”的选择菜单了,鼠标单击管理员账户“administrator”,进入命令行模式。 键入命令:“net user abc /add”(强制将“abc”用户的口令更改为“”)。 若想在此添加一新用户(如:用户名为abcdef,口令为)的话,键入“net user abcdef /add”,添加后可用“net localgroup administrators abcdef /add”命令将用户提升为系统管理组“administrators”用户,并使其具有超级权限。 重启电脑,选择正常模式下运行,就可以用更改后的口令“”登录“abc”用户。 ③如能进入系统或者PE微系统可以使用密码查看器【侠客密码查看器】④嫌麻烦?如果手里有安装光盘,或者u盘PE微系统,一般里面也有破解操作系统登录密码的小工具。 进入PE微系统之后,点选NTPWEdit0.3图标,点选需要进去的账户(比如:Adminstrator)此时更改口令的按钮可用了,分别输入新的密码,再次输入密码予以验证,点击OK即可。 再回到主对话框中点击【保存更改】即可。
免责声明:本文转载或采集自网络,版权归原作者所有。本网站刊发此文旨在传递更多信息,并不代表本网赞同其观点和对其真实性负责。如涉及版权、内容等问题,请联系本网,我们将在第一时间删除。同时,本网站不对所刊发内容的准确性、真实性、完整性、及时性、原创性等进行保证,请读者仅作参考,并请自行核实相关内容。对于因使用或依赖本文内容所产生的任何直接或间接损失,本网站不承担任何责任。