find.zig
· 2.3 KiB · Zig
Неформатований
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 | } |