Refactor builtin commands dispatcher
This commit is contained in:
+22
-31
@@ -8,16 +8,22 @@ const exit = @import("cmds/exit.zig");
|
|||||||
const pwd = @import("cmds/pwd.zig");
|
const pwd = @import("cmds/pwd.zig");
|
||||||
const run = @import("cmds/run.zig");
|
const run = @import("cmds/run.zig");
|
||||||
|
|
||||||
pub const Shell = struct {
|
const types = @import("types.zig");
|
||||||
running: bool = true,
|
|
||||||
interrupted: bool = false,
|
const CommandFn = *const fn (types.BuiltinCommandContext) anyerror!void;
|
||||||
environ: *const std.process.Environ.Map,
|
|
||||||
};
|
const commands = std.StaticStringMap(CommandFn).initComptime(.{
|
||||||
|
.{ "cd", cd.execute },
|
||||||
|
.{ "pwd", pwd.execute },
|
||||||
|
.{ "run", run.execute },
|
||||||
|
.{ "echo", echo.execute },
|
||||||
|
.{ "exit", exit.execute },
|
||||||
|
});
|
||||||
|
|
||||||
pub fn execute(
|
pub fn execute(
|
||||||
io: std.Io,
|
io: std.Io,
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
shell: *Shell,
|
shell: *types.Shell,
|
||||||
command: parser.Command,
|
command: parser.Command,
|
||||||
) !bool {
|
) !bool {
|
||||||
if (command.argv.len == 0)
|
if (command.argv.len == 0)
|
||||||
@@ -25,30 +31,15 @@ pub fn execute(
|
|||||||
|
|
||||||
const name = command.argv[0];
|
const name = command.argv[0];
|
||||||
|
|
||||||
if (std.mem.eql(u8, name, "cd")) {
|
const execute_fn = commands.get(name) orelse
|
||||||
try cd.execute(io, shell.environ, command.argv);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (std.mem.eql(u8, name, "pwd")) {
|
|
||||||
try pwd.execute(io, allocator);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (std.mem.eql(u8, name, "run")) {
|
|
||||||
try run.execute(io, allocator, command.argv);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (std.mem.eql(u8, name, "echo")) {
|
|
||||||
try echo.execute(io, command.argv);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (std.mem.eql(u8, name, "exit")) {
|
|
||||||
exit.execute(&shell.running);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
try execute_fn(.{
|
||||||
|
.io = io,
|
||||||
|
.allocator = allocator,
|
||||||
|
.shell = shell,
|
||||||
|
.argv = command.argv,
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-11
@@ -1,20 +1,18 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub fn execute(
|
const types = @import("../types.zig");
|
||||||
io: std.Io,
|
|
||||||
environ: *const std.process.Environ.Map,
|
pub fn execute(ctx: types.BuiltinCommandContext) !void {
|
||||||
argv: []const []const u8,
|
const path = if (ctx.argv.len >= 2)
|
||||||
) !void {
|
ctx.argv[1]
|
||||||
const path = if (argv.len >= 2)
|
|
||||||
argv[1]
|
|
||||||
else
|
else
|
||||||
environ.get("USERPROFILE") orelse environ.get("HOME") orelse {
|
ctx.shell.environ.get("USERPROFILE") orelse ctx.shell.environ.get("HOME") orelse {
|
||||||
std.debug.print("xsh: cd: cannot find home directory\n", .{});
|
std.debug.print("xsh: cd: cannot find home directory\n", .{});
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
var dir = try std.Io.Dir.cwd().openDir(io, path, .{});
|
var dir = try std.Io.Dir.cwd().openDir(ctx.io, path, .{});
|
||||||
defer dir.close(io);
|
defer dir.close(ctx.io);
|
||||||
|
|
||||||
try std.process.setCurrentDir(io, dir);
|
try std.process.setCurrentDir(ctx.io, dir);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,15 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub fn execute(
|
const types = @import("../types.zig");
|
||||||
io: std.Io,
|
|
||||||
argv: []const []const u8,
|
pub fn execute(ctx: types.BuiltinCommandContext) !void {
|
||||||
) !void {
|
for (ctx.argv[1..], 0..) |argument, index| {
|
||||||
for (argv[1..], 0..) |argument, index| {
|
|
||||||
if (index != 0) {
|
if (index != 0) {
|
||||||
try std.Io.File.stdout().writeStreamingAll(io, " ");
|
try std.Io.File.stdout().writeStreamingAll(ctx.io, " ");
|
||||||
}
|
}
|
||||||
|
|
||||||
try std.Io.File.stdout().writeStreamingAll(io, argument);
|
try std.Io.File.stdout().writeStreamingAll(ctx.io, argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
try std.Io.File.stdout().writeStreamingAll(io, "\n");
|
try std.Io.File.stdout().writeStreamingAll(ctx.io, "\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
pub fn execute(running: *bool) void {
|
const types = @import("../types.zig");
|
||||||
running.* = false;
|
|
||||||
|
pub fn execute(ctx: types.BuiltinCommandContext) !void {
|
||||||
|
ctx.shell.running = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,11 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
pub fn execute(
|
const types = @import("../types.zig");
|
||||||
io: std.Io,
|
|
||||||
allocator: std.mem.Allocator,
|
|
||||||
) !void {
|
|
||||||
const path = try std.process.currentPathAlloc(io, allocator);
|
|
||||||
defer allocator.free(path);
|
|
||||||
|
|
||||||
try std.Io.File.stdout().writeStreamingAll(io, path);
|
pub fn execute(ctx: types.BuiltinCommandContext) !void {
|
||||||
try std.Io.File.stdout().writeStreamingAll(io, "\n");
|
const path = try std.process.currentPathAlloc(ctx.io, ctx.allocator);
|
||||||
|
defer ctx.allocator.free(path);
|
||||||
|
|
||||||
|
try std.Io.File.stdout().writeStreamingAll(ctx.io, path);
|
||||||
|
try std.Io.File.stdout().writeStreamingAll(ctx.io, "\n");
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-13
@@ -2,31 +2,29 @@ const std = @import("std");
|
|||||||
|
|
||||||
const script = @import("../../script/script.zig");
|
const script = @import("../../script/script.zig");
|
||||||
|
|
||||||
pub fn execute(
|
const types = @import("../types.zig");
|
||||||
io: std.Io,
|
|
||||||
allocator: std.mem.Allocator,
|
pub fn execute(ctx: types.BuiltinCommandContext) !void {
|
||||||
argv: []const []const u8,
|
if (ctx.argv.len < 2) {
|
||||||
) !void {
|
|
||||||
if (argv.len < 2) {
|
|
||||||
std.debug.print("xsh: run: missing script path\n", .{});
|
std.debug.print("xsh: run: missing script path\n", .{});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var file = try std.Io.Dir.cwd().openFile(io, argv[1], .{});
|
var file = try std.Io.Dir.cwd().openFile(ctx.io, ctx.argv[1], .{});
|
||||||
defer file.close(io);
|
defer file.close(ctx.io);
|
||||||
|
|
||||||
var file_reader = file.reader(io, &.{});
|
var file_reader = file.reader(ctx.io, &.{});
|
||||||
|
|
||||||
const source = try file_reader.interface.allocRemaining(
|
const source = try file_reader.interface.allocRemaining(
|
||||||
allocator,
|
ctx.allocator,
|
||||||
.limited(16 * 1024 * 1024),
|
.limited(16 * 1024 * 1024),
|
||||||
);
|
);
|
||||||
|
|
||||||
const name_z = try allocator.dupeZ(u8, argv[1]);
|
const name_z = try ctx.allocator.dupeZ(u8, ctx.argv[1]);
|
||||||
|
|
||||||
try script.run(
|
try script.run(
|
||||||
allocator,
|
ctx.allocator,
|
||||||
io,
|
ctx.io,
|
||||||
name_z,
|
name_z,
|
||||||
source,
|
source,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
const std = @import("std");
|
||||||
|
|
||||||
|
pub const Shell = struct {
|
||||||
|
running: bool = true,
|
||||||
|
interrupted: bool = false,
|
||||||
|
environ: *const std.process.Environ.Map,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const BuiltinCommandContext = struct {
|
||||||
|
io: std.Io,
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
shell: *Shell,
|
||||||
|
argv: []const []const u8,
|
||||||
|
};
|
||||||
+3
-2
@@ -5,6 +5,7 @@ const parser = @import("shell/parser.zig");
|
|||||||
const execute = @import("shell/execute.zig");
|
const execute = @import("shell/execute.zig");
|
||||||
|
|
||||||
const builtin = @import("builtin/builtin.zig");
|
const builtin = @import("builtin/builtin.zig");
|
||||||
|
const builtin_types = @import("builtin/types.zig");
|
||||||
|
|
||||||
const script = @import("script/script.zig");
|
const script = @import("script/script.zig");
|
||||||
|
|
||||||
@@ -14,7 +15,7 @@ pub fn main(init: std.process.Init) !void {
|
|||||||
const allocator = init.gpa;
|
const allocator = init.gpa;
|
||||||
const io = init.io;
|
const io = init.io;
|
||||||
|
|
||||||
var shell = builtin.Shell{
|
var shell = builtin_types.Shell{
|
||||||
.environ = init.environ_map,
|
.environ = init.environ_map,
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -55,7 +56,7 @@ pub fn main(init: std.process.Init) !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn runPipeline(allocator: std.mem.Allocator, io: std.Io, shell: *builtin.Shell, source: []const u8) !void {
|
fn runPipeline(allocator: std.mem.Allocator, io: std.Io, shell: *builtin_types.Shell, source: []const u8) !void {
|
||||||
const tokens = try lexer.lex(allocator, source);
|
const tokens = try lexer.lex(allocator, source);
|
||||||
const command = try parser.parse(allocator, tokens.items);
|
const command = try parser.parse(allocator, tokens.items);
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,14 @@
|
|||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
|
|
||||||
const builtin = @import("../builtin/builtin.zig");
|
const builtin = @import("../builtin/builtin.zig");
|
||||||
|
const builtin_types = @import("../builtin/types.zig");
|
||||||
|
|
||||||
const parser = @import("parser.zig");
|
const parser = @import("parser.zig");
|
||||||
|
|
||||||
pub fn run(
|
pub fn run(
|
||||||
io: std.Io,
|
io: std.Io,
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
shell: *builtin.Shell,
|
shell: *builtin_types.Shell,
|
||||||
command: parser.Command,
|
command: parser.Command,
|
||||||
) !void {
|
) !void {
|
||||||
if (try builtin.execute(io, allocator, shell, command))
|
if (try builtin.execute(io, allocator, shell, command))
|
||||||
|
|||||||
Reference in New Issue
Block a user