文盘rust--领域交互模式如何实现

author author     2023-02-14     613

关键词:

作者:京东科技 贾世闻

文盘Rust -- 领域交互模式如何实现

书接上文,上回说到如何通过​​interactcli-rs​​四步实现一个命令行程序。但是shell交互模式在有些场景下用户体验并不是很好。比如我们要连接某个服务,比如mysql或者redis这样的服务。如果每次交互都需要输入地址、端口、用户名等信息,交互起来太麻烦。通常的做法是一次性输入和连接相关的信息或者由统一配置文件进行管理,然后进入领域交互模式,所有的命令和反馈都和该领域相关。​​interactcli-rs​​ 通过 -i 参数实现领域交互模式。这回我们探索一下这一模式是如何实现的。

基本原理

interactcli-rs 实现领域交互模式主要是循环解析输入的每一行,通过​​rustyline​​ 解析输入的每一行命令,并交由命令解析函数处理响应逻辑

当我们调用 ‘-i’ 参数的时候 实际上是执行了 interact::run() 函数(interact -> cli -> run())。

pub fn run() 
let config = Config::builder()
.history_ignore_space(true)
.completion_type(CompletionType::List)
.output_stream(OutputStreamType::Stdout)
.build();

let h = MyHelper
completer: get_command_completer(),
highlighter: MatchingBracketHighlighter::new(),
hinter: HistoryHinter ,
colored_prompt: "".to_owned(),
validator: MatchingBracketValidator::new(),
;

let mut rl = Editor::with_config(config);
rl.set_helper(Some(h));

if rl.load_history("/tmp/history").is_err()
println!("No previous history.");


loop
let p = format!("> ", "interact-rs");
rl.helper_mut().expect("No helper").colored_prompt = format!("\\x1b[1;32m\\x1b[0m", p);
let readline = rl.readline(&p);
match readline
Ok(line) =>
if line.trim_start().is_empty()
continue;


rl.add_history_entry(line.as_str());
match split(line.as_str()).as_mut()
Ok(arg) =>
if arg[0] == "exit"
println!("bye!");
break;

arg.insert(0, "clisample".to_string());
run_from(arg.to_vec())

Err(err) =>
println!("", err)



Err(ReadlineError::Interrupted) =>
println!("CTRL-C");
break;

Err(ReadlineError::Eof) =>
println!("CTRL-D");
break;

Err(err) =>
println!("Error: :?", err);
break;



rl.append_history("/tmp/history")
.map_err(|err| error!("", err))
.ok();

解析主逻辑

交互逻辑主要集中在 ‘loop’ 循环中,每次循环处理一次输入请求。

处理的逻辑如下

  • 定义提示符,类似 mysql> ,提示用户正在使用的程序
let p = format!("> ", "interact-rs");
rl.helper_mut().expect("No helper").colored_prompt = format!("\\x1b[1;32m\\x1b[0m", p);
  • 读取输入行进行解析
  • 将输入的命令行加入到历史文件,执行过的命令可以通过上下键回放来增强用户体验。
rl.add_history_entry(line.as_str());
  • 将输入的行解析为 arg 字符串,交由 cmd::run_from 函数进行命令解析和执行
match split(line.as_str()).as_mut() 
Ok(arg) =>
if arg[0] == "exit"
println!("bye!");
break;

arg.insert(0, "clisample".to_string());
run_from(arg.to_vec())

Err(err) =>
println!("", err)

  • 解析中断,当用户执行 ctrl-c 或 ctrl-d 时,退出程序。
Err(ReadlineError::Interrupted) => 
println!("CTRL-C");
break;

Err(ReadlineError::Eof) =>
println!("CTRL-D");
break;

Err(err) =>
println!("Error: :?", err);
break;

run 函数中其他代码的作用

  • 配置rustyline
    在 run 函数最开头 定义了一个config
let config = Config::builder()
.history_ignore_space(true)
.completion_type(CompletionType::List)
.output_stream(OutputStreamType::Stdout)
.build();

这个config 其实是rustyline的配置项,包括输出方式历史记录约束,输出方式等等。

MyHelper 用于配置命令的 autocomplete

let h = MyHelper 
completer: get_command_completer(),
highlighter: MatchingBracketHighlighter::new(),
hinter: HistoryHinter ,
colored_prompt: "".to_owned(),
validator: MatchingBracketValidator::new(),
;

这里卖个关子,下期详细讲讲 autocomplete 的实现。

  • 配置历史文件
    run 函数最后,我们为程序配置了历史文件,应用于存放执行过的历史命令。这样即便程序退出,在此打开程序的时候还是可以利用以前的执行历史。
rl.append_history("/tmp/history")
.map_err(|err| error!("", err))
.ok();

关于如何构建命令行的领域交互模式就说到这儿,下期详细介绍一下 autocomplete 如何实现。

rust:ctp的rust版本如何手工封装

...装,是指不用外部类似swig专用的库。一、库、配置1、DLL交互的库(1)libloadinghttps://github.com/nagisa/rust_libloading(2)libcRawFFIbindingstoplatformlibrarieslikelibc.https://github.com/rust-lang/libc2、类型转换库Rust封装CTP,涉及两个方面类型,一个... 查看详情

添砖加瓦:设计模式(总述)

...设计模式是由GoF(GangofFour)将模式的概念引入软件工程领域后诞生的。软件模式与具体的应用领域无关。  GoF提出的设计模式有23个,大体可分为三类:  (1)创建型模式:如何创建对象  (2)结构型模式:如何实现类... 查看详情

2023年rust发展如何?

...的语言,它可以满足系统编程的需求,同时也适用于其他领域。2.Rust在2022年的发展趋势在2022年,Rust的发展趋势仍然非常乐观。随着对安全和高效编程的需求日益增长,越来越多的开发者开始使用Rust来开发各种应用程序。此外... 查看详情

如何实现 Rust 的 Copy 特征?

】如何实现Rust的Copy特征?【英文标题】:HowcanIimplementRust\'sCopytrait?【发布时间】:2016-05-2906:24:34【问题描述】:我正在尝试在Rust中初始化一个结构数组:enumDirectionNorth,East,South,West,structRoadPointdirection:Direction,index:i32,//Initialisethea... 查看详情

rust语言如何实现读取yaml配置文件

参考技术A项目根目录添加app.yaml文件cargo.toml最终结果: 查看详情

浅谈java领域模式分层实现(代码片段)

...工更加明确,维护更为便利。而我要介绍的是在java开发领域中,面向对象的分层模式-领域模型分层。领域模型分层最主要的工作就是分离领域,分离领域就是将领域对象与系统中的其他功能分离,从而避免将领域概念和其他只... 查看详情

中介者模式(mediator)笔记

...MediatorPattern):定义一个中介对象来封装系列对象之间的交互。中介者使各个对象不需要显示地相互引用,从而使其耦合性松散,而且可以独立地改变他们之间的交互。 类图:Mediator让Colleague们互相交互的一个抽象Colleague定制... 查看详情

如何在 Rust 结构实现中编写 SPI DMA 代码?

】如何在Rust结构实现中编写SPIDMA代码?【英文标题】:HowtowriteSPIDMAcodeinsideaRuststructimplementation?【发布时间】:2021-05-1517:27:10【问题描述】:我正在尝试使用STM32SPIDMA编写Rust设备驱动程序。如果您查看stm32f1xx-halexample,则SPIDMA代... 查看详情

一天一门编程语言rust语言程序设计极简教程(代码片段)

...型的语法泛型的应用TraitTrait的定义Trait的实现Trait的继承模式匹配模式匹配的语法模式匹配的特性Rust语言模块和结构体什么是结构体实例化结构体结构体的方法结构体的模式匹配结构体的作用Rust语言智能指针一、Rust中什么是智... 查看详情

如何设计领域特定语言,实现终极业务抽象?(代码片段)

在过去的几年里,我一直从事于各种领域定义语言的设计,包含unflow、guarding、datum、forming等。在我刚入门这个领域的时候,我从《领域特定语言》、《编程语言实现模式》等,一直研究到龙书等。我渐渐掌握了... 查看详情

wpf在mvvm模式下实现窗口后台代码与viewmodel交互

...MVVM模式中,UI层基本上与ViewModel通过依赖属性和命令绑定交互。有时候互联网上提供的第三方控件不支持绑定,只能在后台代码中赋值和更新,如何在MVVM模式中对这种特殊的第三方控件实现ViewModel中控制数据。解决方法:1在窗... 查看详情

领域驱动设计(ddd)分层架构的三种模式

...plication为应用层,定义软件要完成的任务,并且指挥表达领域概念的对象来解决问题。这一层所负责的工作对业务来说意义重大,也是与其它系统的应用层进行交互的必要渠道。应用层要尽量简单,不包含业务规则或者知识,而... 查看详情

dba学rust设计模式--观察者模式(代码片段)

#[derive(Debug,Clone)]structWork//消息实体,存储消息id:i32structWorkMaster//消息管理者属性workers:Vec<Box<Worker>>//存储注册的接收者。每个接收者须实现Worker接口才能注册进。implWorkMasterfnregister_worker(&mutself,worker: 查看详情

领域数据库 Swift 3.1 的设计模式 - 单例

】领域数据库Swift3.1的设计模式-单例【英文标题】:DesignPatternforRealmDatabaseSwift3.1-Singleton【发布时间】:2016-03-2203:47:49【问题描述】:我正在研究RealmSwift,它是Swift中CoreData/SQLite的现代数据库替代品。我想知道如何实现Class的设... 查看详情

你熟悉的设计模式都有哪些?写出单例模式的实现代码

...于处理类或对象的组合。行为模式用于描述类或对象如何交互以及如何分配职责,创建模式用于处理对象的创建。主要包括以下五种设计模式:工厂方法模式()抽象工厂模式(AbstractFactoryPattern)建造者模式... 查看详情

使用 AIX 的 ksh 实现以非交互模式读取配置文件脚本

】使用AIX的ksh实现以非交互模式读取配置文件脚本【英文标题】:Readingprofilescriptinnon-interactivemodewithAIXimplementationofksh【发布时间】:2014-08-0714:52:09【问题描述】:请注意,这是一个与AIX相关的问题。我有一个在Redhat上运行的jenki... 查看详情

如何避免 Rust 中重复的长泛型约束

】如何避免Rust中重复的长泛型约束【英文标题】:HowtoavoidrepetitivelonggenericconstraintsinRust【发布时间】:2019-04-0807:56:37【问题描述】:我正在尝试自己实现大整数(仅用于教育)。该实现是按数据类型通用的:structLongNum<T>wher... 查看详情

基于abpframework实现领域驱动设计

这是一份实施领域驱动设计(DDD)的实用指南。虽然实施细节依赖于ABP框架基础设施,但核心概念、原则和模式适用于任何类型的解决方案,即使它不是一个.NET解决方案。简介这是一份实施领域驱动设计(DDD)的实用指南。虽... 查看详情