Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

ShellLibrary.Cmd 完全指南

ShellLibrary.Cmd 是一个为 .NET 应用程序设计的声明式交互式 Shell 框架。你只需要进行简单的配置和命令注册,就能为你的应用快速嵌入一个功能完整、风格可定制的命令行界面(CLI)。它支持管道、外部二进制调用、打字机效果、安全锁定以及批处理脚本执行等特性。

1. 快速开始

首先,在你的项目中引用 ShellLibrary.Cmd 命名空间:

using ShellLibrary.Cmd;

然后,通过静态的 MainLibrary.BuildShell 来配置 Shell 的基本属性并启动它:

// 获取全局 Shell 设置实例
var setting = MainLibrary.BuildShell.ShellSetting;

// 配置 Shell 的外观信息
setting.ShellName = "TutorialShell";
setting.ShellVerion = "0.1";
setting.ShellDescription = "ShellLibrary.Cmd 教程示例";
setting.ShellWelcomeTemplate = true;      // 显示欢迎屏幕
setting.ShellTypwriterstyle = true;       // 启用打字机效果

// (可选)获取命令注册器并添加命令(详见第 2 节)
var registrar = new Register.CommandInfoMake();
registrar.MakeCommandInfo(...);

// 启动 Shell 交互循环
var shell = new MainLibrary.BuildShell();
await shell.BuildAsync();

运行后,你会看到一个带有欢迎屏幕和提示符 > 的命令行交互界面。


2. 命令注册与执行

所有 Shell 内部的命令都需通过 Register.CommandInfoMake 进行注册。每个命令包含名称、描述、用法、帮助文本以及一个执行委托 Func<string?, string[], Task<string>>

2.1 注册一个简单命令

下面的例子注册了一个 echo 命令,它将用户输入的参数拼接后输出到控制台,并将该字符串作为返回值(用于管道传递)。

var registrar = new Register.CommandInfoMake();

registrar.MakeCommandInfo(
    name: "echo",
    description: "输出给定的文本到控制台。",
    usage: "echo <text>",
    commandHelp: "将后续所有参数拼接为字符串并输出。",
    commandAction: async (stdin, args) =>
    {
        var output = string.Join(" ", args);
        Console.WriteLine(output);
        return output;
    }
);

2.2 命令委托参数说明

  • stdin:来自管道中上一个命令传递过来的标准输入字符串。如果该命令不是管道中的一环,则该参数为 null
  • args:用户输入中除去命令名以外的参数数组。
  • 返回值:一个字符串,它会作为当前命令的输出,传递给管道中的下一个命令。如果命令位于管道末尾,则返回值被忽略。

注意:ShellLibrary.Cmd 不会自动将命令返回值打印到控制台。如果你想在控制台上看到输出,必须在命令委托中主动调用 Console.WriteConsole.WriteLine

2.3 批量注册命令

如果你有大量命令,可以使用 BatchMakeCommandInfoAllListCommandInfo 进行批量注册。

var commandList = new List<Register.CommandRegisterInfo>
{
    new Register.CommandRegisterInfo { Name = "cmd1", ... },
    new Register.CommandRegisterInfo { Name = "cmd2", ... }
};
registrar.BatchMakeCommandInfo(commandList);

3. 管道支持

ShellLibrary.Cmd 原生支持使用管道符(默认 |)连接多个命令。在解析时,前一个命令的返回值会被自动传递给后一个命令的 stdin 参数。

示例:假设我们注册了 reverse 命令,它反转输入的字符串。

registrar.MakeCommandInfo(
    name: "reverse",
    description: "反转输入的文本。",
    usage: "reverse",
    commandHelp: "将标准输入或参数中的文本反转。",
    commandAction: async (stdin, args) =>
    {
        var input = stdin ?? string.Join(" ", args);
        var reversed = new string(input.Reverse().ToArray());
        Console.WriteLine(reversed);
        return reversed;
    }
);

用户即可使用管道组合命令:

> echo hello world | reverse
dlrow olleh

你可以通过 MainLibrary.BuildShell.ShellSetting.ShellDelimiter 更改管道分隔符。


4. 调用外部二进制文件

默认情况下,如果用户输入的命令名是一个存在于磁盘上的文件路径(例如 ping/bin/ls),ShellLibrary.Cmd 会尝试启动该文件作为外部进程执行。

此行为由 ShellSetting.ShellRunBinary 控制:

  • true(默认):允许执行外部可执行文件。
  • false:禁止执行任何外部二进制,仅执行内部注册的命令。这有助于创建安全的“受限” Shell 环境。
MainLibrary.BuildShell.ShellSetting.ShellRunBinary = false;

当用户试图执行外部程序时,Shell 将返回 “Command not found.”。


5. 打字机效果与视觉定制

通过配置 TypeWriterShellSetting,你可以控制 Shell 的视觉效果。

5.1 启用打字机效果

setting.ShellTypwriterstyle = true;

启用后,欢迎屏幕的文字会逐字打印,营造复古终端体验。你也可以在自定义命令中调用 MainLibrary.BuildShell.TypeWriter.Write 实现类似效果。

5.2 其他视觉配置

属性 说明
ShellCursorVisible 是否显示控制台光标(true / false
ShellTitle 是否将 Shell 名称设置为控制台窗口标题
ShellWelcomeTemplate 是否在启动时显示欢迎屏幕
setting.ShellCursorVisible = true;
setting.ShellTitle = true;

6. 安全特性:锁定与受限模式

ShellLibrary.Cmd 提供两种维度的安全锁定机制。

6.1 禁止执行外部二进制

如第 4 节所述,设置 ShellRunBinary = false 可以完全阻止用户启动任何外部程序。

6.2 自定义“认知牢笼”

由于命令必须显式注册,你可以通过只注册少量安全命令,来构建一个功能极简的受限 Shell。结合 ShellRunBinary = false,用户即使知道系统命令的路径也无法执行。

setting.ShellRunBinary = false;
registrar.MakeCommandInfo("ls", ...); // 只允许 ls

这种方案比传统 rbash 更加彻底,因为用户无法通过任何方式接触到未注册的命令。


7. 历史记录

ShellLibrary.Cmd 自动记录用户输入的历史命令。记录保存在当前目录的 history.txt 文件中,每条记录附带时间戳。

你可以通过 MainLoop 实例控制该行为:

MainLibrary.BuildShell.MainLoop.HistoryCommandWriteEnabled = false;  // 关闭历史记录

8. 安全退出与信号处理

Shell 内部处理了 Ctrl+C 信号。按一次不会退出;连续按两次将触发安全退出逻辑:先尝试终止正在运行的外部进程(如果有),然后退出 Shell。

你可以通过 MainLoop 的属性进行调整:

var loop = MainLibrary.BuildShell.MainLoop;
loop.SafeExitEnabled = true;      // 是否启用安全退出(按两次 Ctrl+C)
loop.EnabledShellExit = true;     // 是否允许退出 Shell

9. 剧本解析器(批处理脚本)

ShellLibrary.Cmd 包含一个实验性的批处理脚本解析器 SpecializedControlScriptParser,它可以将文本文件中每一行作为命令送入 Shell 执行。

var parser = new SpecializedControlScriptParser();
await parser.Parser("commands.txt");

这对于自动化任务或 CI 场景非常实用。注意:该功能在 0.1.0 版本中已稳定可用,适合小型脚本文件。


10. 高级自定义:消息与提示符

10.1 自定义提示符

MainLibrary.BuildShell.MainLoop.GetTipText = "$ ";   // 默认为 ">"

10.2 自定义错误消息

MessageReops 类包含一个字典,你可以覆盖默认的错误提示。

MainLibrary.BuildShell.MessageReops.Messages["CommandNotFound"] = "未知命令,请输入 help 查看可用命令。";

11. 完整示例:构建一个带帮助系统的迷你 Shell

using ShellLibrary.Cmd;
using ShellLibrary.Cmd.Command;

// 配置 Shell
var setting = MainLibrary.BuildShell.ShellSetting;
setting.ShellName = "MiniShell";
setting.ShellVerion = "1.0";
setting.ShellDescription = "一个带帮助系统的示例 Shell";
setting.ShellWelcomeTemplate = true;
setting.ShellTypwriterstyle = true;
setting.ShellRunBinary = false;

var registrar = new Register.CommandInfoMake();

// 注册 echo 命令
registrar.MakeCommandInfo("echo", "输出文本。", "echo <text>", "打印所有参数。",
    async (stdin, args) => { var s = string.Join(" ", args); Console.WriteLine(s); return s; });

// 注册 clear 命令
registrar.MakeCommandInfo("clear", "清屏。", "clear", "清除控制台内容。",
    async (stdin, args) => { Console.Clear(); return ""; });

// 注册 help 命令
registrar.MakeCommandInfo("help", "显示帮助。", "help", "列出所有命令。",
    async (stdin, args) =>
    {
        foreach (var cmd in MainLibrary.BuildShell.CommandRepository.Commands)
            Console.WriteLine($"{cmd.Key,-10} - {cmd.Value.Description}");
        return "";
    });

// 启动
var shell = new MainLibrary.BuildShell();
await shell.BuildAsync();

12. 结语

ShellLibrary.Cmd 的设计目标是让 .NET 开发者能够以最小的代价,为应用程序赋予一个专业、安全且高度可定制的命令行交互界面。无论是用于调试、管理工具、游戏控制台还是嵌入式设备,它都能提供一套一致且强大的解决方案。

关于 API 的更多细节,请查阅源码注释或项目的 GitHub 仓库。

About

一个用于 .NET 的声明式交互式 Shell 框架。通过简单的配置和命令注册,快速为应用程序嵌入功能完整的命令行界面。

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages