summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/builtins.zig8
-rw-r--r--src/main.zig14
-rw-r--r--src/shell.zig6
-rw-r--r--test_history.txt4
4 files changed, 29 insertions, 3 deletions
diff --git a/src/builtins.zig b/src/builtins.zig
index 2a1eed7..011a923 100644
--- a/src/builtins.zig
+++ b/src/builtins.zig
@@ -1,7 +1,7 @@
const std = @import("std");
const path = @import("path.zig");
-const BUILTINS = [_][]const u8{ "exit", "echo", "type", "pwd", "cd" };
+const BUILTINS = [_][]const u8{ "exit", "echo", "type", "pwd", "cd", "history" };
pub const CommandResult = enum {
continue_loop,
@@ -115,3 +115,9 @@ pub fn executeType(allocator: std.mem.Allocator, stdout: anytype, args: ?[]const
}
}
}
+
+pub fn executeHistory(stdout: anytype, history_list: []const []const u8) !void {
+ for (history_list, 1..) |cmd, idx| {
+ try stdout.print(" {d} {s}\n", .{ idx, cmd });
+ }
+}
diff --git a/src/main.zig b/src/main.zig
index 74140cd..d16699d 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -285,6 +285,12 @@ pub fn main() !void {
defer _ = gpa.deinit();
const allocator = gpa.allocator();
+ var history = std.ArrayList([]const u8){};
+ defer {
+ for (history.items) |cmd| allocator.free(cmd);
+ history.deinit(allocator);
+ }
+
const stdout = std.fs.File.stdout();
while (true) {
@@ -297,6 +303,10 @@ pub fn main() !void {
var stdout_writer = std.fs.File.stdout().writerStreaming(&.{});
const stdout_iface = &stdout_writer.interface;
+ // Record command in history (duplicate it for long-term storage)
+ const cmd_copy = try allocator.dupe(u8, cmd);
+ try history.append(allocator, cmd_copy);
+
if (std.mem.indexOfScalar(u8, cmd, '|')) |_| {
var segments = std.ArrayList([]const u8){};
defer segments.deinit(allocator);
@@ -326,7 +336,7 @@ pub fn main() !void {
if (segments.items.len == 1) {
const parsed = parser.parseCommand(cmd);
- const result = try shell.executeCommand(allocator, stdout_iface, parsed.name, parsed.args, parsed.output_redirect, parsed.error_redirect, parsed.append_output, parsed.append_error);
+ const result = try shell.executeCommand(allocator, stdout_iface, parsed.name, parsed.args, parsed.output_redirect, parsed.error_redirect, parsed.append_output, parsed.append_error, history.items);
if (result == .exit_shell) break;
} else {
const result = try shell.executePipeline(allocator, stdout_iface, segments.items);
@@ -335,7 +345,7 @@ pub fn main() !void {
} else {
const parsed = parser.parseCommand(cmd);
- const result = try shell.executeCommand(allocator, stdout_iface, parsed.name, parsed.args, parsed.output_redirect, parsed.error_redirect, parsed.append_output, parsed.append_error);
+ const result = try shell.executeCommand(allocator, stdout_iface, parsed.name, parsed.args, parsed.output_redirect, parsed.error_redirect, parsed.append_output, parsed.append_error, history.items);
if (result == .exit_shell) break;
}
diff --git a/src/shell.zig b/src/shell.zig
index 271e3ea..6f8bfef 100644
--- a/src/shell.zig
+++ b/src/shell.zig
@@ -19,9 +19,15 @@ pub fn executeCommand(
error_redirect: ?[]const u8,
append_output: ?[]const u8,
append_error: ?[]const u8,
+ history_list: []const []const u8,
) !builtins.CommandResult {
if (std.mem.eql(u8, cmd_name, "exit")) return builtins.executeExit();
+ if (std.mem.eql(u8, cmd_name, "history")) {
+ try builtins.executeHistory(stdout, history_list);
+ return .continue_loop;
+ }
+
if (std.mem.eql(u8, cmd_name, "echo")) {
if (error_redirect) |file| {
const fd = try std.fs.cwd().createFile(file, .{});
diff --git a/test_history.txt b/test_history.txt
new file mode 100644
index 0000000..1f4d742
--- /dev/null
+++ b/test_history.txt
@@ -0,0 +1,4 @@
+echo hello
+pwd
+type echo
+history