summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/builtins.zig38
-rw-r--r--src/main.zig6
-rw-r--r--src/shell.zig9
3 files changed, 50 insertions, 3 deletions
diff --git a/src/builtins.zig b/src/builtins.zig
index 8ce4a6f..4f8dfb8 100644
--- a/src/builtins.zig
+++ b/src/builtins.zig
@@ -181,3 +181,41 @@ pub fn executeHistoryWrite(stdout: anytype, file_path: []const u8, history_list:
try file.writeAll("\n");
}
}
+
+pub fn executeHistoryAppend(stdout: anytype, file_path: []const u8, history_list: []const []const u8, last_written_index: *usize) !void {
+ // Open file in append mode, or create if doesn't exist
+ const file = std.fs.cwd().openFile(file_path, .{ .mode = .write_only }) catch |err| {
+ if (err == error.FileNotFound) {
+ // Create the file if it doesn't exist
+ const new_file = std.fs.cwd().createFile(file_path, .{}) catch {
+ try stdout.print("history: cannot write to {s}: error\n", .{file_path});
+ return;
+ };
+ defer new_file.close();
+
+ // Write all commands to new file
+ for (history_list) |cmd| {
+ try new_file.writeAll(cmd);
+ try new_file.writeAll("\n");
+ }
+ last_written_index.* = history_list.len;
+ return;
+ } else {
+ try stdout.print("history: cannot open {s}: error\n", .{file_path});
+ return;
+ }
+ };
+ defer file.close();
+
+ // Seek to end to append
+ try file.seekFromEnd(0);
+
+ // Append only new commands (commands after last_written_index)
+ const start_idx = last_written_index.*;
+ for (history_list[start_idx..]) |cmd| {
+ try file.writeAll(cmd);
+ try file.writeAll("\n");
+ }
+
+ last_written_index.* = history_list.len;
+}
diff --git a/src/main.zig b/src/main.zig
index 69b40e0..d373826 100644
--- a/src/main.zig
+++ b/src/main.zig
@@ -361,6 +361,8 @@ pub fn main() !void {
history.deinit(allocator);
}
+ var last_written_index: usize = 0;
+
const stdout = std.fs.File.stdout();
while (true) {
@@ -406,7 +408,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, &history);
+ 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, &last_written_index);
if (result == .exit_shell) break;
} else {
const result = try shell.executePipeline(allocator, stdout_iface, segments.items);
@@ -415,7 +417,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, &history);
+ 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, &last_written_index);
if (result == .exit_shell) break;
}
diff --git a/src/shell.zig b/src/shell.zig
index 5a848af..d3f75ec 100644
--- a/src/shell.zig
+++ b/src/shell.zig
@@ -20,11 +20,12 @@ pub fn executeCommand(
append_output: ?[]const u8,
append_error: ?[]const u8,
history: *std.ArrayList([]const u8),
+ last_written_index: *usize,
) !builtins.CommandResult {
if (std.mem.eql(u8, cmd_name, "exit")) return builtins.executeExit();
if (std.mem.eql(u8, cmd_name, "history")) {
- // Check if args contain -r or -w flag for reading/writing file
+ // Check if args contain -r, -w, or -a flag for reading/writing/appending file
if (args) |a| {
const trimmed = std.mem.trim(u8, a, " ");
if (std.mem.startsWith(u8, trimmed, "-r ")) {
@@ -39,6 +40,12 @@ pub fn executeCommand(
try builtins.executeHistoryWrite(stdout, file_path, history.items);
}
return .continue_loop;
+ } else if (std.mem.startsWith(u8, trimmed, "-a ")) {
+ const file_path = std.mem.trim(u8, trimmed[3..], " ");
+ if (file_path.len > 0) {
+ try builtins.executeHistoryAppend(stdout, file_path, history.items, last_written_index);
+ }
+ return .continue_loop;
}
}