From ddf2de739068b5ff0866ccb1d067f3cb53a4fc55 Mon Sep 17 00:00:00 2001 From: David Czihak Date: Thu, 7 May 2026 14:33:19 +0200 Subject: Initial commit --- examples/hello-zig/.editorconfig | 6 ++ examples/hello-zig/.gitignore | 2 + examples/hello-zig/.nova/Configuration.json | 8 +++ examples/hello-zig/.nova/Tasks/Zig Debug.json | 12 ++++ .../.nova/Tasks/Zig Package (macOS Terminal).json | 7 ++ examples/hello-zig/.nova/Tasks/Zig Package.json | 8 +++ examples/hello-zig/build.zig | 47 ++++++++++++ examples/hello-zig/build.zig.zon | 12 ++++ examples/hello-zig/src/main.zig | 32 +++++++++ examples/hello-zig/src/root.zig | 83 ++++++++++++++++++++++ examples/sample-config.zon | 19 +++++ examples/showcase.zig | 80 +++++++++++++++++++++ 12 files changed, 316 insertions(+) create mode 100644 examples/hello-zig/.editorconfig create mode 100644 examples/hello-zig/.gitignore create mode 100644 examples/hello-zig/.nova/Configuration.json create mode 100644 examples/hello-zig/.nova/Tasks/Zig Debug.json create mode 100644 examples/hello-zig/.nova/Tasks/Zig Package (macOS Terminal).json create mode 100644 examples/hello-zig/.nova/Tasks/Zig Package.json create mode 100644 examples/hello-zig/build.zig create mode 100644 examples/hello-zig/build.zig.zon create mode 100644 examples/hello-zig/src/main.zig create mode 100644 examples/hello-zig/src/root.zig create mode 100644 examples/sample-config.zon create mode 100644 examples/showcase.zig (limited to 'examples') diff --git a/examples/hello-zig/.editorconfig b/examples/hello-zig/.editorconfig new file mode 100644 index 0000000..d5f8c65 --- /dev/null +++ b/examples/hello-zig/.editorconfig @@ -0,0 +1,6 @@ +root = true + +[*] +indent_style = space +indent_size = 4 +insert_final_newline = true diff --git a/examples/hello-zig/.gitignore b/examples/hello-zig/.gitignore new file mode 100644 index 0000000..3389c86 --- /dev/null +++ b/examples/hello-zig/.gitignore @@ -0,0 +1,2 @@ +.zig-cache/ +zig-out/ diff --git a/examples/hello-zig/.nova/Configuration.json b/examples/hello-zig/.nova/Configuration.json new file mode 100644 index 0000000..47e341a --- /dev/null +++ b/examples/hello-zig/.nova/Configuration.json @@ -0,0 +1,8 @@ +{ + "at.dcz.nova-zig.toolchain.lldb-dap-path" : "\/Library\/Developer\/CommandLineTools\/usr\/bin\/lldb-dap", + "at.dcz.nova-zig.toolchain.zig-path" : "\/opt\/homebrew\/bin\/zig", + "at.dcz.nova-zig.zls.build-on-save" : true, + "at.dcz.nova-zig.zls.enabled" : true, + "zls.enable_build_on_save" : true, + "zls.zig_exe_path" : "\/opt\/homebrew\/bin\/zig" +} diff --git a/examples/hello-zig/.nova/Tasks/Zig Debug.json b/examples/hello-zig/.nova/Tasks/Zig Debug.json new file mode 100644 index 0000000..53b7f13 --- /dev/null +++ b/examples/hello-zig/.nova/Tasks/Zig Debug.json @@ -0,0 +1,12 @@ +{ + "extension" : { + "identifier" : "at.dcz.nova-zig", + "name" : "Zig" + }, + "extensionTemplate" : "zigDebug", + "extensionValues" : { + "console" : "internalConsole", + "programPath" : "zig-out\/bin\/hello-zig" + }, + "openLogOnRun" : "start" +} diff --git a/examples/hello-zig/.nova/Tasks/Zig Package (macOS Terminal).json b/examples/hello-zig/.nova/Tasks/Zig Package (macOS Terminal).json new file mode 100644 index 0000000..d1fa04d --- /dev/null +++ b/examples/hello-zig/.nova/Tasks/Zig Package (macOS Terminal).json @@ -0,0 +1,7 @@ +{ + "extension" : { + "identifier" : "at.dcz.nova-zig", + "name" : "Zig" + }, + "extensionTemplate" : "zigBuildRunTerminal" +} diff --git a/examples/hello-zig/.nova/Tasks/Zig Package.json b/examples/hello-zig/.nova/Tasks/Zig Package.json new file mode 100644 index 0000000..10830e6 --- /dev/null +++ b/examples/hello-zig/.nova/Tasks/Zig Package.json @@ -0,0 +1,8 @@ +{ + "buildBeforeRunning" : true, + "extension" : { + "identifier" : "at.dcz.nova-zig", + "name" : "Zig" + }, + "extensionTemplate" : "zigBuildRun" +} diff --git a/examples/hello-zig/build.zig b/examples/hello-zig/build.zig new file mode 100644 index 0000000..5c56fb0 --- /dev/null +++ b/examples/hello-zig/build.zig @@ -0,0 +1,47 @@ +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const lib_mod = b.addModule("hello_zig", .{ + .root_source_file = b.path("src/root.zig"), + .target = target, + }); + + const exe = b.addExecutable(.{ + .name = "hello-zig", + .root_module = b.createModule(.{ + .root_source_file = b.path("src/main.zig"), + .target = target, + .optimize = optimize, + .imports = &.{ + .{ .name = "hello_zig", .module = lib_mod }, + }, + }), + }); + + b.installArtifact(exe); + + const run_step = b.step("run", "Run the sample app"); + const run_cmd = b.addRunArtifact(exe); + run_step.dependOn(&run_cmd.step); + + if (b.args) |args| { + run_cmd.addArgs(args); + } + + const lib_tests = b.addTest(.{ + .root_module = lib_mod, + }); + const exe_tests = b.addTest(.{ + .root_module = exe.root_module, + }); + + const run_lib_tests = b.addRunArtifact(lib_tests); + const run_exe_tests = b.addRunArtifact(exe_tests); + + const test_step = b.step("test", "Run the sample tests"); + test_step.dependOn(&run_lib_tests.step); + test_step.dependOn(&run_exe_tests.step); +} diff --git a/examples/hello-zig/build.zig.zon b/examples/hello-zig/build.zig.zon new file mode 100644 index 0000000..09f7da2 --- /dev/null +++ b/examples/hello-zig/build.zig.zon @@ -0,0 +1,12 @@ +.{ + .name = .hello_zig, + .version = "0.1.0", + .fingerprint = 0x1c1a468675f426fe, // Changing this has security and trust implications. + .minimum_zig_version = "0.15.2", + .dependencies = .{}, + .paths = .{ + "build.zig", + "build.zig.zon", + "src", + }, +} diff --git a/examples/hello-zig/src/main.zig b/examples/hello-zig/src/main.zig new file mode 100644 index 0000000..74eb590 --- /dev/null +++ b/examples/hello-zig/src/main.zig @@ -0,0 +1,32 @@ +const std = @import("std"); +const hello_zig = @import("hello_zig"); + +pub fn main() !void { + var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); + defer arena.deinit(); + + const allocator = arena.allocator(); + const args = try std.process.argsAlloc(allocator); + const name = if (args.len > 1) args[1] else "Nova"; + + var greeter = hello_zig.Greeter{ + .name = name, + .punctuation = '!', + }; + + const stdout = std.fs.File.stdout().deprecatedWriter(); + try greeter.write(stdout, .verbose); + + const sample_values = [_]i32{ -3, -2, 0, 1, 2, 3, 4 }; + var squares = try hello_zig.collectEvenSquares(allocator, &sample_values); + defer squares.deinit(allocator); + + std.debug.print("even squares: {any}\n", .{squares.items}); +} + +test "main module can compute a summary" { + const greeting = try hello_zig.describeNumber(std.testing.allocator, 42); + defer std.testing.allocator.free(greeting); + + try std.testing.expect(std.mem.startsWith(u8, greeting, "positive")); +} diff --git a/examples/hello-zig/src/root.zig b/examples/hello-zig/src/root.zig new file mode 100644 index 0000000..f6600ac --- /dev/null +++ b/examples/hello-zig/src/root.zig @@ -0,0 +1,83 @@ +const std = @import("std"); + +pub const OutputStyle = enum { + compact, + verbose, +}; + +pub const NumberKind = union(enum) { + negative: i64, + zero, + positive: u64, +}; + +pub const Greeter = struct { + name: []const u8, + punctuation: u8 = '!', + + pub fn write(self: Greeter, writer: anytype, style: OutputStyle) !void { + switch (style) { + .compact => try writer.print("hello, {s}{c}\n", .{ self.name, self.punctuation }), + .verbose => { + try writer.print( + \\hello, {s}{c} + \\this sample is here to exercise Zig syntax support in Nova. + \\ + , .{ self.name, self.punctuation }); + }, + } + } +}; + +pub fn classifyNumber(value: i64) NumberKind { + if (value == 0) return .zero; + if (value < 0) return .{ .negative = value }; + return .{ .positive = @intCast(value) }; +} + +pub fn describeNumber(allocator: std.mem.Allocator, value: i64) ![]u8 { + return switch (classifyNumber(value)) { + .zero => std.fmt.allocPrint(allocator, "zero", .{}), + .negative => |negative| std.fmt.allocPrint(allocator, "negative({d})", .{negative}), + .positive => |positive| std.fmt.allocPrint(allocator, "positive({d})", .{positive}), + }; +} + +pub fn collectEvenSquares( + allocator: std.mem.Allocator, + values: []const i32, +) !std.ArrayList(i32) { + var result: std.ArrayList(i32) = .empty; + errdefer result.deinit(allocator); + + for (values) |value| { + if (@mod(value, 2) != 0) continue; + try result.append(allocator, value * value); + } + + return result; +} + +test "classifyNumber covers the main branches" { + try std.testing.expectEqual(NumberKind{ .negative = -5 }, classifyNumber(-5)); + try std.testing.expectEqual(NumberKind.zero, classifyNumber(0)); + try std.testing.expectEqual(NumberKind{ .positive = 9 }, classifyNumber(9)); +} + +test "collectEvenSquares keeps only even numbers" { + const values = [_]i32{ -4, -3, 0, 1, 2, 7 }; + var result = try collectEvenSquares(std.testing.allocator, &values); + defer result.deinit(std.testing.allocator); + + try std.testing.expectEqualSlices(i32, &.{ 16, 0, 4 }, result.items); +} + +test "Greeter.write renders verbose output" { + var list: std.ArrayList(u8) = .empty; + defer list.deinit(std.testing.allocator); + + const writer = list.writer(std.testing.allocator); + try (Greeter{ .name = "Zig" }).write(writer, .verbose); + + try std.testing.expect(std.mem.indexOf(u8, list.items, "exercise Zig syntax support") != null); +} diff --git a/examples/sample-config.zon b/examples/sample-config.zon new file mode 100644 index 0000000..b346a84 --- /dev/null +++ b/examples/sample-config.zon @@ -0,0 +1,19 @@ +.{ + .name = "nova-zig-example", + .enabled = true, + .targets = .{ + "native", + "wasm32-wasi", + }, + .retry = .{ + .max_attempts = 3, + .backoff_seconds = 2.5, + }, + .theme = .solarized, + .features = .{ + .language_server = true, + .tree_sitter = true, + .run_tasks = true, + .debug_adapter = false, + }, +} diff --git a/examples/showcase.zig b/examples/showcase.zig new file mode 100644 index 0000000..54b195f --- /dev/null +++ b/examples/showcase.zig @@ -0,0 +1,80 @@ +const std = @import("std"); + +pub const AppError = error{ + MissingName, + EmptyInput, +}; + +pub const Theme = enum { + light, + dark, + solarized, +}; + +pub const Settings = struct { + name: []const u8, + retries: u8 = 3, + theme: Theme = .dark, + tags: []const []const u8 = &.{}, + + pub fn validate(self: Settings) AppError!void { + if (self.name.len == 0) return error.MissingName; + if (self.tags.len == 0) return error.EmptyInput; + } +}; + +pub fn summarize(settings: Settings) []const u8 { + return switch (settings.theme) { + .light => "bright", + .dark => "focused", + .solarized => "balanced", + }; +} + +pub fn findLongestTag(tags: []const []const u8) ?[]const u8 { + var longest: ?[]const u8 = null; + + for (tags) |tag| { + if (longest == null or tag.len > longest.?.len) { + longest = tag; + } + } + + return longest; +} + +pub fn renderExample(writer: anytype) !void { + const settings = Settings{ + .name = "Nova Zig", + .tags = &.{ "tree-sitter", "zls", "tasks" }, + }; + + try settings.validate(); + try writer.print("theme summary: {s}\n", .{summarize(settings)}); + + if (findLongestTag(settings.tags)) |tag| { + try writer.print("longest tag: {s}\n", .{tag}); + } + + const block_value = label: { + var total: usize = 0; + for (settings.tags) |tag| total += tag.len; + break :label total; + }; + try writer.print("combined tag length: {}\n", .{block_value}); + + const multiline = + \\sample text block + \\with enough lines to make folding obvious + \\inside Nova's editor + ; + _ = multiline; +} + +test "showcase remains valid" { + var output: std.ArrayList(u8) = .empty; + defer output.deinit(std.testing.allocator); + + try renderExample(output.writer(std.testing.allocator)); + try std.testing.expect(std.mem.indexOf(u8, output.items, "theme summary") != null); +} -- cgit v1.3