Rust命令行工具库nu-cli的使用,nu-cli提供高效终端交互与脚本解析功能
Rust命令行工具库nu-cli的使用,nu-cli提供高效终端交互与脚本解析功能
简介
nu-cli crate实现了Nushell交互式REPL的核心功能,并与reedline
集成。目前实现了语法高亮和自动补全逻辑,还包含一些针对reedline
的特定命令。
内部Nushell crate
这个crate实现了Nushell的组件,主要供内部使用,不直接支持插件开发或其他外部用户。
安装
在项目目录中运行以下Cargo命令:
cargo add nu-cli
或在Cargo.toml中添加以下行:
nu-cli = "0.106.1"
示例代码
以下是一个使用nu-cli创建简单REPL的示例:
use nu_cli::{
create_default_context,
evaluate_script,
evaluate_repl,
EvaluationContext
};
fn main() {
// 创建默认上下文
let mut context = create_default_context().unwrap();
// 评估脚本
let script = "echo 'Hello, NuShell!'";
let result = evaluate_script(&mut context, script);
println!("Script evaluation result: {:?}", result);
// 启动REPL
println!("Starting REPL...");
evaluate_repl(&mut context).unwrap();
}
更完整的示例
下面是一个更完整的示例,展示了如何使用nu-cli创建自定义命令和处理输入:
use nu_cli::{
create_default_context,
evaluate_script,
EvaluationContext,
CommandRegistry
};
use nu_protocol::{Signature, Value, ShellError};
// 自定义命令
fn my_command(context: &EvaluationContext, args: Vec<Value>) -> Result<Value, ShellError> {
println!("Custom command executed with args: {:?}", args);
Ok(Value::nothing())
}
fn main() {
// 创建默认上下文
let mut context = create_default_context().unwrap();
// 获取命令注册表
let mut registry = CommandRegistry::new();
// 注册自定义命令
registry.register_command(
"mycmd", // 命令名
Signature::build("mycmd"), // 命令签名
my_command // 命令处理函数
);
// 将注册表添加到上下文中
context.add_commands(registry);
// 评估使用自定义命令的脚本
let script = r#"
echo "Before custom command"
mycmd arg1 arg2
echo "After custom command"
"#;
match evaluate_script(&mut context, script) {
Ok(_) => println!("Script executed successfully"),
Err(e) => eprintln!("Error executing script: {:?}", e),
}
}
完整示例demo
以下是一个更全面的nu-cli使用示例,展示了REPL交互、自定义命令和脚本评估的完整功能:
use nu_cli::{
create_default_context,
evaluate_script,
evaluate_repl,
EvaluationContext,
CommandRegistry
};
use nu_protocol::{Signature, Value, ShellError};
// 自定义计算命令
fn calculate(_: &EvaluationContext, args: Vec<Value>) -> Result<Value, ShellError> {
if args.len() < 3 {
return Err(ShellError::MissingParameter {
param_name: "operator and operands".to_string(),
span: None,
});
}
let op = args[0].as_string()?;
let x = args[1].as_i64()?;
let y = args[2].as_i64()?;
let result = match op.as_str() {
"+" => x + y,
"-" => x - y,
"*" => x * y,
"/" => x / y,
_ => return Err(ShellError::UnsupportedOperator(op)),
};
Ok(Value::int(result, None))
}
// 自定义问候命令
fn greet(_: &EvaluationContext, args: Vec<Value>) -> Result<Value, ShellError> {
let name = if !args.is_empty() {
args[0].as_string()?
} else {
"World".to_string()
};
println!("Hello, {}!", name);
Ok(Value::nothing())
}
fn main() {
// 创建默认上下文
let mut context = create_default_context().unwrap();
// 创建命令注册表
let mut registry = CommandRegistry::new();
// 注册自定义命令
registry.register_command(
"calc",
Signature::build("calc")
.required("operator", SyntaxShape::String)
.required("x", SyntaxShape::Int)
.required("y", SyntaxShape::Int),
calculate
);
registry.register_command(
"greet",
Signature::build("greet").optional("name", SyntaxShape::String),
greet
);
// 将命令添加到上下文
context.add_commands(registry);
// 评估脚本示例
let script = r#"
echo "开始计算演示"
calc + 10 5
calc * 3 7
echo "开始问候演示"
greet
greet "Nushell"
"#;
println!("执行脚本:");
match evaluate_script(&mut context, script) {
Ok(output) => println!("脚本输出: {:?}", output),
Err(e) => eprintln!("脚本执行错误: {:?}", e),
}
// 启动交互式REPL
println!("启动REPL,输入'exit'退出");
evaluate_repl(&mut context).unwrap();
}
文档
更多详细信息和API参考请参阅官方文档。
注意
nu-cli主要是Nushell的内部组件,如果您需要构建命令行应用程序,可能需要考虑其他更通用的Rust CLI库如clap或structopt。
1 回复
Rust命令行工具库nu-cli的使用指南
介绍
nu-cli是一个用Rust编写的命令行工具库,提供了高效的终端交互和脚本解析功能。它源自流行的nushell项目,专注于为开发者提供强大的命令行处理能力。
主要特性:
- 高性能的终端交互
- 强大的脚本解析引擎
- 灵活的管道操作
- 丰富的内置命令
- 易于扩展的插件系统
安装方法
在Cargo.toml中添加依赖:
[dependencies]
nu-cli = "0.60" # 请使用最新版本
基本使用方法
1. 创建简单的CLI应用
use nu_cli::{create_default_context, run_command};
use nu_parser::parse;
use nu_protocol::engine::StateWorkingSet;
fn main() {
// 创建执行上下文
let mut context = create_default_context().unwrap();
// 解析并执行命令
let input = "echo 'Hello, nu-cli!'";
let (block, _) = parse(&mut StateWorkingSet::new(&context.engine_state), input, false);
match run_command(&block, &mut context, None) {
Ok(_) => println!("Command executed successfully"),
Err(e) => eprintln!("Error: {}", e),
}
}
2. 处理管道操作
use nu_cli::{create_default_context, run_command};
use nu_parser::parse;
use nu_protocol::engine::StateWorkingSet;
fn main() {
let mut context = create_default_context().unwrap();
// 管道示例:获取当前目录文件并筛选出.rs文件
let input = "ls | where name =~ '..rs$'";
let (block, _) = parse(&mut StateWorkingSet::new(&context.engine_state), input, false);
run_command(&block, &mut context, None).unwrap();
}
3. 自定义命令
use nu_cli::{create_default_context, run_command};
use nu_engine::eval_block;
use nu_parser::parse;
use nu_protocol::{
engine::{EngineState, StateWorkingSet},
Signature, Value,
};
use nu_protocol::{Example, PipelineData, ShellError, Span};
// 定义自定义命令
fn hello_command(args: &[Value], _: &EngineState) -> Result<PipelineData, ShellError> {
let name = if args.is_empty() {
"World".to_string()
} else {
args[0].as_string()?
};
Ok(PipelineData::Value(Value::String {
val: format!("Hello, {}!", name),
span: Span::unknown(),
}))
}
fn main() {
let mut context = create_default_context().unwrap();
// 添加自定义命令到引擎状态
context.engine_state.add_command(
"hello".to_string(),
Signature::build("hello").optional("name", "The name to greet"),
hello_command,
);
// 使用自定义命令
let input = "hello \"nu-cli\"";
let (block, _) = parse(&mut StateWorkingSet::new(&context.engine_state), input, false);
run_command(&block, &mut context, None).unwrap();
}
高级功能
1. 脚本执行
use nu_cli::{create_default_context, run_script};
use std::path::Path;
fn main() {
let mut context = create_default_context().unwrap();
// 执行脚本文件
let script_path = Path::new("example.nu");
match run_script(&mut context, script_path, None) {
Ok(_) => println!("Script executed successfully"),
Err(e) => eprintln!("Error: {}", e),
}
}
2. 交互式终端
use nu_cli::create_default_context;
use nu_cli::run_repl;
fn main() {
let mut context = create_default_context().unwrap();
// 启动交互式REPL
if let Err(e) = run_repl(&mut context) {
eprintln!("REPL error: {}", e);
}
}
实际应用示例
文件处理管道
use nu_cli::{create_default_context, run_command};
use nu_parser::parse;
use nu_protocol::engine::StateWorkingSet;
fn main() {
let mut context = create_default_context().unwrap();
// 复杂管道示例:统计当前目录下.rs文件的行数
let input = r#"
ls *.rs
| each { |file|
open $file.name
| lines
| length
| { name: $file.name, lines: $in }
}
| sort-by lines -r
| first 5
"#;
let (block, _) = parse(&mut StateWorkingSet::new(&context.engine_state), input, false);
run_command(&block, &mut context, None).unwrap();
}
完整示例DEMO
下面是一个结合多个功能的完整示例,展示如何创建一个支持自定义命令、管道操作和脚本执行的CLI应用:
use nu_cli::{create_default_context, run_command, run_script};
use nu_engine::eval_block;
use nu_parser::parse;
use nu_protocol::{
engine::{EngineState, StateWorkingSet},
Signature, Value,
};
use nu_protocol::{PipelineData, ShellError, Span};
use std::path::Path;
// 自定义命令:计算平方
fn square_command(args: &[Value], _: &EngineState) -> Result<PipelineData, ShellError> {
let num = if args.is_empty() {
0
} else {
args[0].as_int()?
};
Ok(PipelineData::Value(Value::Int {
val: num * num,
span: Span::unknown(),
}))
}
fn main() {
// 创建上下文
let mut context = create_default_context().unwrap();
// 添加自定义命令
context.engine_state.add_command(
"square".to_string(),
Signature::build("square").required("number", "The number to square"),
square_command,
);
// 示例1: 使用自定义命令
println!("=== 示例1: 使用自定义命令 ===");
let input1 = "square 5";
let (block1, _) = parse(&mut StateWorkingSet::new(&context.engine_state), input1, false);
run_command(&block1, &mut context, None).unwrap();
// 示例2: 管道操作
println!("\n=== 示例2: 管道操作 ===");
let input2 = "1..10 | each { |it| square $it } | math sum";
let (block2, _) = parse(&mut StateWorkingSet::new(&context.engine_state), input2, false);
run_command(&block2, &mut context, None).unwrap();
// 示例3: 执行脚本文件
println!("\n=== 示例3: 执行脚本文件 ===");
let script_path = Path::new("demo.nu");
if let Err(e) = run_script(&mut context, script_path, None) {
eprintln!("没有找到脚本文件 demo.nu,跳过此示例");
}
// 示例4: 启动交互式REPL
println!("\n=== 示例4: 启动交互式REPL ===");
println!("输入 exit 退出REPL");
if let Err(e) = nu_cli::run_repl(&mut context) {
eprintln!("REPL error: {}", e);
}
}
注意事项
- nu-cli仍在积极开发中,API可能会有变动
- 错误处理应使用
Result
模式,妥善处理可能的错误 - 对于性能敏感的应用,建议复用
EngineState
和Context
对象
nu-cli为Rust开发者提供了强大的命令行处理能力,特别适合需要复杂命令行交互或脚本支持的应用程序开发。