91 lines
2.9 KiB
Zig
91 lines
2.9 KiB
Zig
const std = @import("std");
|
|
const TextWriter = std.ArrayList(u8).Writer;
|
|
|
|
pub fn find_first_non_ws(text: []const u8) ?usize {
|
|
for (text, 0..) |c, i| if (c == ' ' or c == '\t') continue else return i;
|
|
return null;
|
|
}
|
|
|
|
pub fn find_prefix(prefix: []const u8, text: []const u8) ?usize {
|
|
var start: usize = 0;
|
|
var pos: usize = 0;
|
|
var in_prefix: bool = false;
|
|
for (text, 0..) |c, i| {
|
|
if (!in_prefix) {
|
|
if (c == ' ' or c == '\t')
|
|
continue
|
|
else {
|
|
in_prefix = true;
|
|
start = i;
|
|
}
|
|
}
|
|
|
|
if (in_prefix) {
|
|
if (c == prefix[pos]) {
|
|
pos += 1;
|
|
if (prefix.len > pos) continue else return start;
|
|
} else return null;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
fn add_prefix_in_line(prefix: []const u8, text: []const u8, writer: TextWriter, pos: usize) !void {
|
|
if (text.len >= pos and find_first_non_ws(text) != null) {
|
|
_ = try writer.write(text[0..pos]);
|
|
_ = try writer.write(prefix);
|
|
_ = try writer.write(" ");
|
|
_ = try writer.write(text[pos..]);
|
|
} else {
|
|
_ = try writer.write(text);
|
|
}
|
|
}
|
|
|
|
fn remove_prefix_in_line(prefix: []const u8, text: []const u8, writer: TextWriter) !void {
|
|
if (find_prefix(prefix, text)) |pos| {
|
|
_ = try writer.write(text[0..pos]);
|
|
if (text.len > pos + prefix.len) {
|
|
_ = try if (text[pos + prefix.len] == ' ')
|
|
writer.write(text[pos + 1 + prefix.len ..])
|
|
else
|
|
writer.write(text[pos + prefix.len ..]);
|
|
}
|
|
} else {
|
|
_ = try writer.write(text);
|
|
}
|
|
}
|
|
|
|
pub fn toggle_prefix_in_text(prefix: []const u8, text: []const u8, allocator: std.mem.Allocator) ![]const u8 {
|
|
var result = try std.ArrayList(u8).initCapacity(allocator, prefix.len + text.len);
|
|
const writer = result.writer();
|
|
var pos: usize = 0;
|
|
var prefix_pos: usize = std.math.maxInt(usize);
|
|
var have_prefix = true;
|
|
while (std.mem.indexOfScalarPos(u8, text, pos, '\n')) |next| {
|
|
if (find_prefix(prefix, text[pos..next])) |_| {} else {
|
|
if (find_first_non_ws(text[pos..next])) |_| {
|
|
have_prefix = false;
|
|
break;
|
|
}
|
|
}
|
|
pos = next + 1;
|
|
}
|
|
pos = 0;
|
|
if (!have_prefix)
|
|
while (std.mem.indexOfScalarPos(u8, text, pos, '\n')) |next| {
|
|
if (find_first_non_ws(text[pos..next])) |prefix_pos_|
|
|
prefix_pos = @min(prefix_pos, prefix_pos_);
|
|
pos = next + 1;
|
|
};
|
|
pos = 0;
|
|
while (std.mem.indexOfScalarPos(u8, text, pos, '\n')) |next| {
|
|
if (have_prefix) {
|
|
try remove_prefix_in_line(prefix, text[pos..next], writer);
|
|
} else {
|
|
try add_prefix_in_line(prefix, text[pos..next], writer, prefix_pos);
|
|
}
|
|
_ = try writer.write("\n");
|
|
pos = next + 1;
|
|
}
|
|
return result.toOwnedSlice();
|
|
}
|