Last active 1719877009

Find a pattern in a file, print the content of the file and mark the position of the pattern (if found)

find.zig Raw
1const std = @import("std");
2
3const COLOR_RED = "\x1b[0;31m";
4const COLOR_RESET = "\x1b[0m";
5
6fn print_usage(exec: [*:0]u8) void {
7 std.debug.print("Usage: {s} FILE PATTERN\n", .{exec});
8}
9
10fn string_contains_substring(allocator: std.mem.Allocator, string: []u8, substring: []u8) !std.ArrayList([2]usize) {
11 var list = std.ArrayList([2]usize).init(allocator);
12
13 var start: ?usize = null;
14 var substring_index: usize = 0;
15
16 for (string, 0..) |c, i| {
17 if (c == substring[substring_index]) {
18 substring_index += 1;
19
20 if (substring_index == substring.len) {
21 try list.append(.{ start orelse i, i });
22 start = null;
23 substring_index = 0;
24 continue;
25 }
26
27 if (start == null) {
28 start = i;
29 }
30 } else if (start != null) {
31 start = null;
32 substring_index = 0;
33 }
34 }
35
36 return list;
37}
38
39pub fn main() !void {
40 if (std.os.argv.len != 3) {
41 print_usage(std.os.argv[0]);
42 std.process.exit(1);
43 unreachable;
44 }
45
46 const stdout = std.io.getStdOut().writer();
47
48 var gpa = std.heap.GeneralPurposeAllocator(.{}){};
49 const allocator = gpa.allocator();
50 defer {
51 const status = gpa.deinit();
52 if (status == .leak) @panic("there are leaks");
53 }
54
55 const args = try std.process.argsAlloc(allocator);
56 defer std.process.argsFree(allocator, args);
57
58 const file = try std.fs.cwd().openFile(args[1], .{});
59 defer file.close();
60
61 const reader = file.reader();
62 while (true) {
63 const line = reader.readUntilDelimiterAlloc(allocator, '\n', 1024 * 1024) catch break;
64 defer allocator.free(line);
65 const contains = try string_contains_substring(allocator, line, args[2]);
66 defer contains.deinit();
67
68 if (contains.items.len == 0) {
69 try stdout.print(" {s}\n", .{line});
70 } else {
71 try stdout.print("> ", .{});
72 var previous: usize = 0;
73 for (contains.items) |element| {
74 try stdout.print("{s}{s}{s}{s}", .{ line[previous..element[0]], COLOR_RED, line[element[0] .. element[1] + 1], COLOR_RESET });
75 previous = element[1] + 1;
76 }
77 try stdout.print("{s}\n", .{line[previous..]});
78 }
79 }
80}