ringtailsoftware/zig-embshell
Small embeddable command line shell in zig
A very small interactive command shell for (embedded) Zig programs.
EmbShell makes an ideal system monitor for debugging and interacting with a small embedded system. It interactively takes lines of text, parses commands and makes callbacks into handler functions.
Compared with Readline, Linenoise and Editline - EmbShell is tiny. It lacks most of their features, but it does have:
std
(ie. no fancy print formatting)In EmbShell:
comptime
to optimise footprintDeveloped with zig 0.14.0
cd example-posix
zig build run
myshell> help
echo
led
myshell> echo hello world
You said: { echo, hello, world }
OK
myshell> led 1
If we had an LED it would be set to true
OK
First add the library as a dependency in your build.zig.zon
file.
zig fetch --save git+https://github.com/ringtailsoftware/zig-embshell.git
And add it to build.zig
file.
const embshell_dep = b.dependency("embshell", .{
.target = target,
.optimize = optimize,
});
exe.root_module.addImport("embshell", embshell_dep.module("embshell"));
@import
the module and provide a configuration.
.prompt
is the string shown to the user before each command is entered.maxargs
is the maximum number of arguments EmbShell will process (e.g. "mycmd foo bar" is 3 arguments).maxlinelen
is the maximum length of a line to be handled, a buffer of this size will be created.cmdtable
an array of names and handler function for commandsconst UserdataT = u32;
const EmbShellT = @import("embshell").EmbShellFixedParams(UserdataT);
const EmbShell = @import("embshell").EmbShellFixed(.{
.prompt = "myshell> ",
.maxargs = 16,
.maxlinelen = 128,
.cmdtable = &.{
.{ .name = "echo", .handler = echoHandler },
.{ .name = "led", .handler = ledHandler },
},
.userdataT = UserdataT,
});
Each handler function is in the following form. EmbShell prints "OK" after successfully executing each function and "Failed" if an error is returned.
fn myHandler(userdata: UserdataT, args:[][]const u8) anyerror!void {
// process args
// optionally return error
}
Next, call .init()
and provide a write callback to allow EmbShell to emit data
fn write(data:[]const u8) void {
// emit data to terminal
}
var shell = try EmbShell.init(write, userdata);
Finally, feed EmbShell with incoming data from the terminal to be processed
const buf = readFromMyTerminal();
shell.feed(buf)