Skip to content

Commit

Permalink
library: refactor C library for filter updates
Browse files Browse the repository at this point in the history
  • Loading branch information
natecraddock committed Dec 10, 2022
1 parent 47467d2 commit f9f17d9
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 30 deletions.
129 changes: 129 additions & 0 deletions src/clib.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
const filter = @import("filter.zig");
const std = @import("std");
const testing = std.testing;

/// rank a given string against a slice of tokens
export fn rank(
str: [*:0]const u8,
filename: ?[*:0]const u8,
tokens: [*]const [*:0]const u8,
num_tokens: usize,
case_sensitive: bool,
) f64 {
const string = std.mem.span(str);
const name = if (filename != null) std.mem.span(filename) else null;

var total_rank: f64 = 0;
var index: usize = 0;
while (index < num_tokens) : (index += 1) {
const token = std.mem.span(tokens[index]);
if (filter.rankToken(string, name, token, !case_sensitive)) |r| {
total_rank += r;
} else return -1.0;
}
return total_rank;
}

/// rank a given string against a single token
export fn rankToken(
str: [*:0]const u8,
filename: ?[*:0]const u8,
token: [*:0]const u8,
case_sensitive: bool,
) f64 {
const string = std.mem.span(str);
const name = if (filename != null) std.mem.span(filename) else null;
const tok = std.mem.span(token);
if (filter.rankToken(string, name, tok, !case_sensitive)) |r| {
return r;
} else return -1.0;
}

test "rank exported C library interface" {
{
const tokens: [2][*:0]const u8 = .{ "a", "z" };
try testing.expect(rank("abcdefg", null, &tokens, 2, false) == -1);
}
{
const tokens: [2][*:0]const u8 = .{ "a", "b" };
try testing.expect(rank("abcdefg", null, &tokens, 2, false) != -1);
}
{
const tokens: [2][*:0]const u8 = .{ "a", "B" };
try testing.expect(rank("abcdefg", null, &tokens, 2, true) == -1);
}
{
const tokens: [2][*:0]const u8 = .{ "a", "B" };
try testing.expect(rank("aBcdefg", null, &tokens, 2, true) != -1);
}
{
const tokens: [1][*:0]const u8 = .{"zig"};
try testing.expect(rank("a/path/to/file", null, &tokens, 2, false) == -1);
}
{
const tokens: [2][*:0]const u8 = .{ "path", "file" };
try testing.expect(rank("a/path/to/file", "file", &tokens, 2, false) != -1);
}

try testing.expect(rankToken("abcdefg", null, "a", false) != -1);
try testing.expect(rankToken("abcdefg", null, "z", false) == -1);
try testing.expect(rankToken("abcdefG", null, "G", true) != -1);
try testing.expect(rankToken("abcdefg", null, "A", true) == -1);
try testing.expect(rankToken("a/path/to/file", "file", "file", false) != -1);
try testing.expect(rankToken("a/path/to/file", "file", "zig", false) == -1);
}

const Range = filter.Range;

export fn highlight(
str: [*:0]const u8,
filename: ?[*:0]const u8,
ranges: [*]Range,
tokens: [*]const [*:0]const u8,
num: usize,
case_sensitive: bool,
) void {
const string = std.mem.span(str);
const name = if (filename != null) std.mem.span(filename) else null;

var index: usize = 0;
while (index < num) : (index += 1) {
const token = std.mem.span(tokens[index]);
ranges[index] = filter.highlightToken(string, name, token, !case_sensitive);
}
}

export fn highlightToken(
str: [*:0]const u8,
filename: ?[*:0]const u8,
token: [*:0]const u8,
case_sensitive: bool,
) Range {
const string = std.mem.span(str);
const name = if (filename != null) std.mem.span(filename) else null;
const tok = std.mem.span(token);
return filter.highlightToken(string, name, tok, !case_sensitive);
}

fn testHighlight(
expectedRanges: []const Range,
str: [*:0]const u8,
filename: ?[*:0]const u8,
tokens: []const [*:0]const u8,
case_sensitive: bool,
) !void {
var ranges = try testing.allocator.alloc(Range, tokens.len);
defer testing.allocator.free(ranges);
highlight(str, filename, ranges.ptr, tokens.ptr, ranges.len, case_sensitive);
try testing.expectEqualSlices(Range, expectedRanges, ranges);
}

test "highlight exported C library interface" {
try testHighlight(&.{ .{ .start = 0, .end = 0 }, .{ .start = 5, .end = 5 } }, "abcdef", null, &.{ "a", "f" }, false);
try testHighlight(&.{ .{ .start = 0, .end = 0 }, .{ .start = 5, .end = 5 } }, "abcdeF", null, &.{ "a", "F" }, true);
try testHighlight(&.{ .{ .start = 2, .end = 5 }, .{ .start = 10, .end = 13 } }, "a/path/to/file", "file", &.{ "path", "file" }, false);

try testing.expectEqual(Range{ .start = 0, .end = 0 }, highlightToken("abcdef", null, "a", false));
try testing.expectEqual(Range{ .start = 5, .end = 5 }, highlightToken("abcdeF", null, "F", true));
try testing.expectEqual(Range{ .start = 10, .end = 13 }, highlightToken("a/path/to/file", "file", "file", false));
}
3 changes: 2 additions & 1 deletion src/filter.zig
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ pub const Candidate = struct {
rank: f64 = 0,
};

pub const Range = struct {
/// Packed so it can be exported via the C ABI
pub const Range = packed struct {
start: usize = 0,
end: usize = 0,
};
Expand Down
29 changes: 0 additions & 29 deletions src/libzf.zig

This file was deleted.

1 change: 1 addition & 0 deletions src/main.zig
Original file line number Diff line number Diff line change
Expand Up @@ -287,4 +287,5 @@ pub fn readAll(allocator: std.mem.Allocator, reader: *std.fs.File.Reader) ![]u8
test {
_ = @import("filter.zig");
_ = @import("lib.zig");
_ = @import("clib.zig");
}

0 comments on commit f9f17d9

Please sign in to comment.