find.zig
· 2.3 KiB · Zig
Raw
const std = @import("std");
const COLOR_RED = "\x1b[0;31m";
const COLOR_RESET = "\x1b[0m";
fn print_usage(exec: [*:0]u8) void {
std.debug.print("Usage: {s} FILE PATTERN\n", .{exec});
}
fn string_contains_substring(allocator: std.mem.Allocator, string: []u8, substring: []u8) !std.ArrayList([2]usize) {
var list = std.ArrayList([2]usize).init(allocator);
var start: ?usize = null;
var substring_index: usize = 0;
for (string, 0..) |c, i| {
if (c == substring[substring_index]) {
substring_index += 1;
if (substring_index == substring.len) {
try list.append(.{ start orelse i, i });
start = null;
substring_index = 0;
continue;
}
if (start == null) {
start = i;
}
} else if (start != null) {
start = null;
substring_index = 0;
}
}
return list;
}
pub fn main() !void {
if (std.os.argv.len != 3) {
print_usage(std.os.argv[0]);
std.process.exit(1);
unreachable;
}
const stdout = std.io.getStdOut().writer();
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
defer {
const status = gpa.deinit();
if (status == .leak) @panic("there are leaks");
}
const args = try std.process.argsAlloc(allocator);
defer std.process.argsFree(allocator, args);
const file = try std.fs.cwd().openFile(args[1], .{});
defer file.close();
const reader = file.reader();
while (true) {
const line = reader.readUntilDelimiterAlloc(allocator, '\n', 1024 * 1024) catch break;
defer allocator.free(line);
const contains = try string_contains_substring(allocator, line, args[2]);
defer contains.deinit();
if (contains.items.len == 0) {
try stdout.print(" {s}\n", .{line});
} else {
try stdout.print("> ", .{});
var previous: usize = 0;
for (contains.items) |element| {
try stdout.print("{s}{s}{s}{s}", .{ line[previous..element[0]], COLOR_RED, line[element[0] .. element[1] + 1], COLOR_RESET });
previous = element[1] + 1;
}
try stdout.print("{s}\n", .{line[previous..]});
}
}
}
1 | const std = @import("std"); |
2 | |
3 | const COLOR_RED = "\x1b[0;31m"; |
4 | const COLOR_RESET = "\x1b[0m"; |
5 | |
6 | fn print_usage(exec: [*:0]u8) void { |
7 | std.debug.print("Usage: {s} FILE PATTERN\n", .{exec}); |
8 | } |
9 | |
10 | fn 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 | |
39 | pub 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 | } |