├── .gitignore ├── LICENSE ├── README.md ├── build.zig ├── build.zig.zon └── src └── main.zig /.gitignore: -------------------------------------------------------------------------------- 1 | /zig-cache 2 | /zig-out 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 zls-as-lib-demo contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # zls-as-lib-demo 2 | 3 | An example of the Zig Language Server (ZLS) being used as a library. Simply build and run this then type `std.` or `zls.`, then enter to see completions. 4 | 5 | Oh hi ~~Mark~~Ben. 6 | 7 | ## License 8 | 9 | MIT 10 | -------------------------------------------------------------------------------- /build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | pub fn build(b: *std.Build) void { 4 | const target = b.standardTargetOptions(.{}); 5 | const optimize = b.standardOptimizeOption(.{}); 6 | 7 | const exe = b.addExecutable(.{ 8 | .name = "zls-as-lib-demo", 9 | .root_source_file = .{ .path = "src/main.zig" }, 10 | .target = target, 11 | .optimize = optimize, 12 | }); 13 | exe.addModule("zls", b.dependency("zls", .{}).module("zls")); 14 | exe.install(); 15 | 16 | const run_cmd = exe.run(); 17 | 18 | run_cmd.step.dependOn(b.getInstallStep()); 19 | 20 | if (b.args) |args| { 21 | run_cmd.addArgs(args); 22 | } 23 | 24 | const run_step = b.step("run", "Run the app"); 25 | run_step.dependOn(&run_cmd.step); 26 | 27 | const exe_tests = b.addTest(.{ 28 | .root_source_file = .{ .path = "src/main.zig" }, 29 | .target = target, 30 | .optimize = optimize, 31 | }); 32 | 33 | const test_step = b.step("test", "Run unit tests"); 34 | test_step.dependOn(&exe_tests.step); 35 | } 36 | -------------------------------------------------------------------------------- /build.zig.zon: -------------------------------------------------------------------------------- 1 | .{ 2 | .name = "scip-zig", 3 | .version = "1.0.0", 4 | .dependencies = .{ 5 | .zls = .{ 6 | .url = "https://github.com/zigtools/zls/archive/build-runner-param-plus-library.tar.gz", 7 | .hash = "1220d72a4bc8e8c934d3854b29e065cbe7d09328c83368b0e658d3f6c0acd7424d92", 8 | }, 9 | }, 10 | } 11 | -------------------------------------------------------------------------------- /src/main.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const zls = @import("zls"); 3 | 4 | pub const std_options = struct { 5 | pub const log_level = .debug; 6 | 7 | pub fn logFn( 8 | comptime level: std.log.Level, 9 | comptime scope: @TypeOf(.EnumLiteral), 10 | comptime format: []const u8, 11 | args: anytype, 12 | ) void { 13 | if (comptime std.mem.startsWith(u8, @tagName(scope), "zls_")) return; 14 | std.log.defaultLog(level, scope, format, args); 15 | } 16 | }; 17 | 18 | pub fn main() !void { 19 | const allocator = std.heap.page_allocator; 20 | 21 | // We start by initing a config and zig version 22 | // wrapper which determines what features 23 | // zls can safely use 24 | var config = zls.Config{}; 25 | var version: ?zls.ZigVersionWrapper = null; 26 | 27 | // Running configChanged on start is required 28 | // to populate the config options 29 | try zls.configuration.configChanged(&config, &version, allocator, null); 30 | 31 | // Create a server, then set its encoding 32 | // to utf-8 so we can use the same indices 33 | // as a normal zig []const u8 34 | var server = try zls.Server.create(allocator, &config, null, false, false); 35 | server.offset_encoding = .@"utf-8"; 36 | defer server.destroy(); 37 | 38 | // We open a BS document with an absolute path 39 | // which is currently required; the text is empty 40 | // as we're going to refresh it anyways 41 | const bs_uri = try allocator.dupe(u8, "file:///C:/Programming/Zig/zls-as-lib-demo/src/bs.zig"); 42 | // NOTE: This function takes ownership of the input `text` 43 | _ = try server.document_store.openDocument(bs_uri, try allocator.dupeZ(u8, "")); 44 | 45 | try std.io.getStdOut().writer().writeAll("Enter an input for completion below: (Try `std.` and `zls.`)\n"); 46 | 47 | var input_buf: [1024]u8 = undefined; 48 | while (true) { 49 | // Free the server arena if it's past 50 | // a certain threshold 51 | defer server.maybeFreeArena(); 52 | 53 | var stdio = std.io.getStdIn().reader(); 54 | const input = stdio.readUntilDelimiterOrEof(&input_buf, '\n') catch |err| switch (err) { 55 | error.StreamTooLong => { 56 | std.debug.print("Input too long (max length is 1024 bytes)", .{}); 57 | return err; 58 | }, 59 | else => return err, 60 | } orelse return; 61 | 62 | // We replace the content of the document with our input in the right context 63 | // NOTE: This function takes ownership of the input `text` 64 | try server.document_store.refreshDocument(bs_uri, try std.fmt.allocPrintZ(allocator, 65 | \\const std = @import("std"); 66 | \\const zls = @import("zls"); 67 | \\ 68 | \\pub fn neverGonnaGiveYouUpNeverGonnaLetYouDown() {{ 69 | \\ {s} 70 | \\}} 71 | , .{input})); 72 | 73 | // We request completions from zls 74 | const completions: []const zls.types.CompletionItem = (try server.completionHandler(.{ 75 | .textDocument = .{ 76 | .uri = "file:///C:/Programming/Zig/zls-as-lib-demo/src/bs.zig", 77 | }, 78 | .position = .{ 79 | .line = 4, 80 | .character = @intCast(u32, 4 + input.len), 81 | }, 82 | }) orelse zls.types.CompletionList{ .isIncomplete = true, .items = &.{} }).items; 83 | 84 | // We print out the completions 85 | for (completions) |comp| { 86 | try std.io.getStdOut().writer().print(" {s}\n", .{comp.label}); 87 | } 88 | } 89 | } 90 | --------------------------------------------------------------------------------