Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

query_exec_fallible

main.query_exec_fallible
fn query_exec_fallible(query: []const u8, ignore_case: bool) !void

File

lib/docs/wasm/main.zig:99

Code

fn query_exec_fallible(query: []const u8, ignore_case: bool) !void {
    const Score = packed struct(u32) {
        points: u16,
        segments: u16,
    };
    const g = struct {
        var full_path_search_text: ArrayList(u8) = .empty;
        var full_path_search_text_lower: ArrayList(u8) = .empty;
        var doc_search_text: ArrayList(u8) = .empty;
        /// Each element matches a corresponding query_results element.
        var scores: ArrayList(Score) = .empty;
    };

    // First element stores the size of the list.
    try query_results.resize(gpa, 1);
    // Corresponding point value is meaningless and therefore undefined.
    try g.scores.resize(gpa, 1);

    decl_loop: for (Walk.decls.items, 0..) |*decl, decl_index| {
        const info = decl.extra_info();
        if (!info.is_pub) continue;

        try decl.reset_with_path(&g.full_path_search_text);
        if (decl.parent != .none)
            try Decl.append_parent_ns(&g.full_path_search_text, decl.parent);
        try g.full_path_search_text.appendSlice(gpa, info.name);

        try g.full_path_search_text_lower.resize(gpa, g.full_path_search_text.items.len);
        @memcpy(g.full_path_search_text_lower.items, g.full_path_search_text.items);

        const ast = decl.file.get_ast();
        if (info.first_doc_comment.unwrap()) |first_doc_comment| {
            try collect_docs(&g.doc_search_text, ast, first_doc_comment);
        }

        if (ignore_case) {
            ascii_lower(g.full_path_search_text_lower.items);
            ascii_lower(g.doc_search_text.items);
        }

        var it = std.mem.tokenizeScalar(u8, query, ' ');
        var points: u16 = 0;
        var bypass_limit = false;
        while (it.next()) |term| {
            // exact, case sensitive match of full decl path
            if (std.mem.eql(u8, g.full_path_search_text.items, term)) {
                points += 4;
                bypass_limit = true;
                continue;
            }
            // exact, case sensitive match of just decl name
            if (std.mem.eql(u8, info.name, term)) {
                points += 3;
                bypass_limit = true;
                continue;
            }
            // substring, case insensitive match of full decl path
            if (std.mem.indexOf(u8, g.full_path_search_text_lower.items, term) != null) {
                points += 2;
                continue;
            }
            if (std.mem.indexOf(u8, g.doc_search_text.items, term) != null) {
                points += 1;
                continue;
            }
            continue :decl_loop;
        }

        if (query_results.items.len < max_matched_items or bypass_limit) {
            try query_results.append(gpa, @fromBackingInt(@intCast(decl_index)));
            try g.scores.append(gpa, .{
                .points = points,
                .segments = @intCast(count_scalar(g.full_path_search_text.items, '.')),
            });
        }
    }

    const sort_context: struct {
        pub fn swap(sc: @This(), a_index: usize, b_index: usize) void {
            _ = sc;
            std.mem.swap(Score, &g.scores.items[a_index], &g.scores.items[b_index]);
            std.mem.swap(Decl.Index, &query_results.items[a_index], &query_results.items[b_index]);
        }

        pub fn lessThan(sc: @This(), a_index: usize, b_index: usize) bool {
            _ = sc;
            const a_score = g.scores.items[a_index];
            const b_score = g.scores.items[b_index];
            if (b_score.points < a_score.points) {
                return true;
            } else if (b_score.points > a_score.points) {
                return false;
            } else if (a_score.segments < b_score.segments) {
                return true;
            } else if (a_score.segments > b_score.segments) {
                return false;
            } else {
                const a_decl = query_results.items[a_index];
                const b_decl = query_results.items[b_index];
                const a_file_path = a_decl.get().file.path();
                const b_file_path = b_decl.get().file.path();
                // This neglects to check the local namespace inside the file.
                return std.mem.lessThan(u8, b_file_path, a_file_path);
            }
        }
    } = .{};

    std.mem.sortUnstableContext(1, query_results.items.len, sort_context);

    if (query_results.items.len > max_matched_items)
        query_results.shrinkRetainingCapacity(max_matched_items);
}