From 5722710573c7d76f8f3d8608892e34045f417b0f Mon Sep 17 00:00:00 2001 From: Ibrahim <80769933+ibrahimalizade@users.noreply.github.com> Date: Wed, 19 Aug 2026 21:50:15 +0400 Subject: [PATCH 1/8] Add Zig highlighting --- zig.lsh | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 zig.lsh diff --git a/zig.lsh b/zig.lsh new file mode 100644 index 00000000000..bc0c899000b --- /dev/null +++ b/zig.lsh @@ -0,0 +1,52 @@ +#[display_name = "Zig"] +#[path = "**/*.zig"] +#[path = "**/*.zon"] +pub fn zig() { + until /$/ { + yield other; + + if /\/\/.*/ { + yield comment; + } else if /\\\\.*/ { + yield string; + } else if /"/ { + loop { + if /\\./ { + } else if /"/ { + yield string; + break; + } else if /$/ { + yield string; + break; + } else if /./ {} + } + } else if /'(\\.|[^'\\])'/ { + yield string; + } else if /@([a-zA-Z_]\w*)\s*\(/ { + yield $1 as method; + } else if /@[a-zA-Z_]\w*/ { + yield storage.annotation; + } else if /(?:break|continue|return|try|catch|orelse|if|else|switch|while|for|suspend|resume|async|await|defer|errdefer|unreachable)\>/ { + yield keyword.control; + } else if /(?:const|var|fn|pub|usingnamespace|struct|enum|union|error|opaque|inline|noinline|comptime|callconv|volatile|allowzero|align|linksection|threadlocal|anytype)\>/ { + yield keyword.other; + } else if /(?:true|false|null|undefined|nil)\>/ { + yield constant.language; + } else if /(?:i\d+|u\d+|f16|f32|f64|f128|isize|usize|bool|void|noreturn|type|anyerror)\>/ { + yield storage.type; + } else if /-?(?:0x[0-9a-fA-F_]+|0b[01_]+|0o[0-7_]+|\d[\d_]*(?:\.\d[\d_]*)?)\>/ { + if /\w+/ { + } else { + yield constant.numeric; + } + } else if /\.[a-zA-Z_]\w*/ { + yield variable; // Catches ZON field keys like .name, .version + } else if /(\w+)\s*\(/ { + yield $1 as method; + } else if /\w+/ { + // Gobble word chars + } + + yield other; + } +} \ No newline at end of file From 624236aaa4bc9e03bdd726d32e1e415ce45ed3db Mon Sep 17 00:00:00 2001 From: Ibrahim <80769933+ibrahimalizade@users.noreply.github.com> Date: Wed, 19 Aug 2026 22:15:15 +0400 Subject: [PATCH 2/8] Add Zig highlight test file --- test.zig | 189 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 189 insertions(+) create mode 100644 test.zig diff --git a/test.zig b/test.zig new file mode 100644 index 00000000000..f42ee8545f1 --- /dev/null +++ b/test.zig @@ -0,0 +1,189 @@ +// Single-line comment +/// Documentation comment. + +// Imports +const std = @import("std"); +const builtin = @import("builtin"); + +// Constants and variables +const answer: i32 = 42; +const pi = 3.14159; +var counter: usize = 0; +pub const name = "Zig"; + +// Integer literals +const decimal = 123; +const binary = 0b1010_0101; +const octal = 0o755; +const hex = 0xDEAD_BEEF; +const separated = 1_000_000; + +// Floating-point literals +const float = 3.14; +const exponent = 1.5e-3; +const hex_float = 0x1.8p1; + +// Character and string literals +const char = 'a'; +const newline = '\n'; +const unicode = '\u{1F600}'; +const string = "escapes: \" \\ \n \t"; + +// Multiline string +const multiline = + \\first line + \\second line +; + +// Identifiers +const @"quoted identifier" = 123; +const snake_case = true; + +// Operators +const arithmetic = 1 + 2 * 3 - 4 / 2 % 2; +const comparison = a == b and c != d or e >= f; +const bitwise = x & y | z ^ w; +const shifts = value << 2 >> 1; +const wrapping = a +% b; +const saturating = a +| b; + +// Struct +const Point = struct { + x: i32, + y: i32, + + pub fn init(x: i32, y: i32) Point { + return .{ .x = x, .y = y }; + } +}; + +const origin = Point{ + .x = 0, + .y = 0, +}; + +// Enum +const Color = enum { + red, + green, + blue, +}; + +// Tagged union +const Value = union(enum) { + integer: i64, + float: f64, + boolean: bool, +}; + +// Arrays, slices, tuples +const array = [_]u8{ 1, 2, 3, 4 }; +const slice = array[1..3]; +const tuple = .{ 42, true, "hello" }; + +// Pointers +var value: i32 = 42; +const ptr: *i32 = &value; +const many_ptr: [*]i32 = undefined; +const sentinel_ptr: [*:0]const u8 = undefined; + +// Functions +fn add(a: i32, b: i32) i32 { + return a + b; +} + +fn generic(comptime T: type, value: T) T { + return value; +} + +// If / else +fn classify(x: i32) i32 { + if (x > 10) { + return 1; + } else if (x == 10) { + return 0; + } else { + return -1; + } +} + +// While / for / labels +fn loops() void { + var i: usize = 0; + + while (i < 10) : (i += 1) { + if (i == 5) continue; + if (i == 8) break; + } + + for (array, 0..) |item, index| { + _ = item; + _ = index; + } + + outer: for (array) |item| { + if (item == 3) break :outer; + } +} + +// Switch +fn describe(value: Value) void { + switch (value) { + .integer => |x| _ = x, + .float => |x| _ = x, + .boolean => |x| _ = x, + } +} + +// Optionals +fn optional(value: ?i32) i32 { + return value orelse 0; +} + +// Errors +const MyError = error{ + NotFound, + InvalidValue, +}; + +fn mightFail() MyError!i32 { + return error.NotFound; +} + +fn handleError() !void { + const result = try mightFail(); + _ = result; + + _ = mightFail() catch 42; +} + +// Defer +fn cleanup() void { + defer std.debug.print("done\n", .{}); +} + +// Comptime / builtins +const type_of_value = @TypeOf(value); +const size_of_point = @sizeOf(Point); +const alignment = @alignOf(Point); +const field_name = @tagName(Color.red); + +// Builtin-heavy expression +const converted = @intCast(@as(u64, 42)); +const bits = @bitCast(@as(u32, 0x3F800000)); + +// Extern / export / calling convention +extern fn external_function(x: i32) i32; + +export fn exported_function(x: i32) callconv(.c) i32 { + return x; +} + +// Tests +test "basic arithmetic" { + try std.testing.expect(add(1, 2) == 3); +} + +test "optional" { + try std.testing.expect(optional(null) == 0); +} \ No newline at end of file From 08e8557072b9ba41012f55b23269774041d5f69f Mon Sep 17 00:00:00 2001 From: Ibrahim <80769933+ibrahimalizade@users.noreply.github.com> Date: Fri, 21 Aug 2026 11:09:20 +0400 Subject: [PATCH 3/8] Move file to right folder and rename it --- test.zig => assets/highlighting-tests/zig.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename test.zig => assets/highlighting-tests/zig.zig (99%) diff --git a/test.zig b/assets/highlighting-tests/zig.zig similarity index 99% rename from test.zig rename to assets/highlighting-tests/zig.zig index f42ee8545f1..4d09f058433 100644 --- a/test.zig +++ b/assets/highlighting-tests/zig.zig @@ -186,4 +186,4 @@ test "basic arithmetic" { test "optional" { try std.testing.expect(optional(null) == 0); -} \ No newline at end of file +} From 089c34d7961e303ced8b4f8c6c54b91f6a47af0d Mon Sep 17 00:00:00 2001 From: Ibrahim <80769933+ibrahimalizade@users.noreply.github.com> Date: Fri, 21 Aug 2026 11:12:32 +0400 Subject: [PATCH 4/8] Move file to right place --- zig.lsh => crates/lsh/definitions/zig.lsh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename zig.lsh => crates/lsh/definitions/zig.lsh (99%) diff --git a/zig.lsh b/crates/lsh/definitions/zig.lsh similarity index 99% rename from zig.lsh rename to crates/lsh/definitions/zig.lsh index bc0c899000b..d9b0cedefe2 100644 --- a/zig.lsh +++ b/crates/lsh/definitions/zig.lsh @@ -49,4 +49,4 @@ pub fn zig() { yield other; } -} \ No newline at end of file +} From c831a21644345a97cb714b7626e215e32cc69b99 Mon Sep 17 00:00:00 2001 From: ibrahimalizade Date: Sat, 29 Aug 2026 12:57:47 +0400 Subject: [PATCH 5/8] Rewrite basiclly --- crates/lsh/definitions/zig.lsh | 43 +++++++++++++--------------------- 1 file changed, 16 insertions(+), 27 deletions(-) diff --git a/crates/lsh/definitions/zig.lsh b/crates/lsh/definitions/zig.lsh index d9b0cedefe2..99c66f2a798 100644 --- a/crates/lsh/definitions/zig.lsh +++ b/crates/lsh/definitions/zig.lsh @@ -7,46 +7,35 @@ pub fn zig() { if /\/\/.*/ { yield comment; - } else if /\\\\.*/ { - yield string; + } + else if /'/ { + single_quote_string(); } else if /"/ { - loop { - if /\\./ { - } else if /"/ { - yield string; - break; - } else if /$/ { - yield string; - break; - } else if /./ {} - } - } else if /'(\\.|[^'\\])'/ { - yield string; - } else if /@([a-zA-Z_]\w*)\s*\(/ { - yield $1 as method; - } else if /@[a-zA-Z_]\w*/ { - yield storage.annotation; - } else if /(?:break|continue|return|try|catch|orelse|if|else|switch|while|for|suspend|resume|async|await|defer|errdefer|unreachable)\>/ { + double_quote_string(); + } else if /(?:break|continue|try|defer|else|errdefer|for|if|return|switch|unreachable|while)\>/ { yield keyword.control; - } else if /(?:const|var|fn|pub|usingnamespace|struct|enum|union|error|opaque|inline|noinline|comptime|callconv|volatile|allowzero|align|linksection|threadlocal|anytype)\>/ { + } else if /(?:addrspace|align|allowzero|and|anyframe|anytype|asm|callconv|catch|comptime|const|enum|error|export|extern|fn|inline|linksection|noalias|noinline|nosuspend|opaque|or|orelse|packed|pub|resume|struct|suspend|test|threadlocal|union|var|volatile)\>/ { yield keyword.other; - } else if /(?:true|false|null|undefined|nil)\>/ { + } else if /(?:true|false|null|undefined)\>/ { yield constant.language; - } else if /(?:i\d+|u\d+|f16|f32|f64|f128|isize|usize|bool|void|noreturn|type|anyerror)\>/ { + } else if /(?:bool|void|noreturn|type|anytype|anyerror|anyframe|anyopaque|isize|usize|comptime_int|comptime_float|f16|f32|f64|f80|f128)\>/ { yield storage.type; - } else if /-?(?:0x[0-9a-fA-F_]+|0b[01_]+|0o[0-7_]+|\d[\d_]*(?:\.\d[\d_]*)?)\>/ { + } else if /(?:c_char|c_short|c_ushort|c_int|c_uint|c_long|c_ulong|c_longlong|c_ulonglong|c_longdouble)\>/ { // C ABI compatibility types + yield storage.type; + } else if /(?:[iu]\d+)\>/ { // i8, u32, i128, u7, etc. + yield storage.type; + } else if /(?i:-?(?:0x[\da-f_]+|0b[01_]+|0o[0-7_]+|[\d_]+(?:\.[\d_]*)?|\.[\d_]+)(?:[eEpP][+-]?[\d_]+)?)/ { if /\w+/ { + // Invalid numeric literal } else { yield constant.numeric; } - } else if /\.[a-zA-Z_]\w*/ { - yield variable; // Catches ZON field keys like .name, .version } else if /(\w+)\s*\(/ { yield $1 as method; } else if /\w+/ { - // Gobble word chars + // Gobble word chars to align the next iteration on a word boundary. } yield other; } -} +} \ No newline at end of file From 7fc22da659687c6e44f117cc3d2fe82e1bcf9a5d Mon Sep 17 00:00:00 2001 From: ibrahimalizade Date: Sun, 30 Aug 2026 17:27:36 +0400 Subject: [PATCH 6/8] Added highlight for built-in functions --- crates/lsh/definitions/zig.lsh | 31 ++++++++++++++++++++++--------- 1 file changed, 22 insertions(+), 9 deletions(-) diff --git a/crates/lsh/definitions/zig.lsh b/crates/lsh/definitions/zig.lsh index 99c66f2a798..d6cea2bd17a 100644 --- a/crates/lsh/definitions/zig.lsh +++ b/crates/lsh/definitions/zig.lsh @@ -4,11 +4,23 @@ pub fn zig() { until /$/ { yield other; - if /\/\/.*/ { yield comment; - } - else if /'/ { + } else if /\s*\\\\/ { + // finish the rest of the current line + until /$/ {} + + // keep consuming lines that start with optional spaces + \\ + loop { + await input; + if /\s*\\\\/ { + until /$/ {} + } else { + break; + } + } + yield string; + } else if /'/ { single_quote_string(); } else if /"/ { double_quote_string(); @@ -20,22 +32,23 @@ pub fn zig() { yield constant.language; } else if /(?:bool|void|noreturn|type|anytype|anyerror|anyframe|anyopaque|isize|usize|comptime_int|comptime_float|f16|f32|f64|f80|f128)\>/ { yield storage.type; - } else if /(?:c_char|c_short|c_ushort|c_int|c_uint|c_long|c_ulong|c_longlong|c_ulonglong|c_longdouble)\>/ { // C ABI compatibility types - yield storage.type; - } else if /(?:[iu]\d+)\>/ { // i8, u32, i128, u7, etc. - yield storage.type; - } else if /(?i:-?(?:0x[\da-f_]+|0b[01_]+|0o[0-7_]+|[\d_]+(?:\.[\d_]*)?|\.[\d_]+)(?:[eEpP][+-]?[\d_]+)?)/ { + } else if /(?:c_char|c_short|c_ushort|c_int|c_uint|c_long|c_ulong|c_ulonglong|c_longlong|c_longdouble)\>/ { + yield storage.type; + } else if /(?:[iu]\d+)\>/ { + yield storage.type; + } else if /(?i:-?(?:0x[\da-f_]+|0b[01_]+|0o[0-7_]+|[\d_]+(?:\.[\d_]*)?|\.[\d_]+)(?:[eEpP][+-]?[\d_]+)?)/ { if /\w+/ { // Invalid numeric literal } else { yield constant.numeric; } + } else if /@([a-zA-Z_]\w*)/ { + yield method; } else if /(\w+)\s*\(/ { yield $1 as method; } else if /\w+/ { // Gobble word chars to align the next iteration on a word boundary. } - yield other; } } \ No newline at end of file From 436b2052758c6f8d6fcb05eb91b6b52d00c77c55 Mon Sep 17 00:00:00 2001 From: ibrahimalizade Date: Tue, 1 Sep 2026 12:28:29 +0400 Subject: [PATCH 7/8] Fix multi-line strings --- crates/lsh/definitions/zig.lsh | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/crates/lsh/definitions/zig.lsh b/crates/lsh/definitions/zig.lsh index d6cea2bd17a..464d53b8375 100644 --- a/crates/lsh/definitions/zig.lsh +++ b/crates/lsh/definitions/zig.lsh @@ -6,21 +6,20 @@ pub fn zig() { yield other; if /\/\/.*/ { yield comment; - } else if /\s*\\\\/ { - // finish the rest of the current line - until /$/ {} - - // keep consuming lines that start with optional spaces + \\ - loop { - await input; - if /\s*\\\\/ { - until /$/ {} - } else { - break; - } - } - yield string; - } else if /'/ { + } else if /\s*\\\\/ { + until /$/ {} + yield string; + + loop { + await input; + if /\s*\\\\/ { + until /$/ {} + yield string; + } else { + break; + } + } + } else if /'/ { single_quote_string(); } else if /"/ { double_quote_string(); From dcc885abe479041e02e7de524c873a7d9c1824e7 Mon Sep 17 00:00:00 2001 From: Leonard Hecker Date: Thu, 1 Oct 2026 21:52:58 +0200 Subject: [PATCH 8/8] Simplify --- assets/highlighting-tests/zig.zig | 36 ++++++++++++++++++++++++++++++ crates/lsh/definitions/zig.lsh | 37 +++++++++++-------------------- 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/assets/highlighting-tests/zig.zig b/assets/highlighting-tests/zig.zig index 4d09f058433..76075f0120e 100644 --- a/assets/highlighting-tests/zig.zig +++ b/assets/highlighting-tests/zig.zig @@ -22,6 +22,10 @@ const separated = 1_000_000; const float = 3.14; const exponent = 1.5e-3; const hex_float = 0x1.8p1; +const hex_fraction = 0xAB.CD; +const hex_exponent = 0x1P+4; +const separated_float = 1_000.125_000E+2; +const separated_hex_float = 0x1234_5678.9ABC_CDEFp-10; // Character and string literals const char = 'a'; @@ -32,12 +36,21 @@ const string = "escapes: \" \\ \n \t"; // Multiline string const multiline = \\first line + \\ \\second line + \\"quotes", // comments, @builtins, and 123 are literal text +; +const inline_multiline = \\starts on the declaration line ; // Identifiers const @"quoted identifier" = 123; const snake_case = true; +const @"if" = @"quoted identifier"; +const @"escaped \"quote\"" = "// not a comment"; +const _123 = 123; +const u8_count = 8; +const iffy = false; // Operators const arithmetic = 1 + 2 * 3 - 4 / 2 % 2; @@ -79,6 +92,8 @@ const Value = union(enum) { // Arrays, slices, tuples const array = [_]u8{ 1, 2, 3, 4 }; const slice = array[1..3]; +const open_slice = array[1..]; +const hex_slice = array[0x1..0x3]; const tuple = .{ 42, true, "hello" }; // Pointers @@ -96,6 +111,20 @@ fn generic(comptime T: type, value: T) T { return value; } +fn inferred(argument: anytype) @TypeOf(argument) { + return argument; +} + +extern fn cFunction(argument: c_int, pointer: *anyopaque) c_longdouble; + +const CTypes = .{ c_char, c_short, c_ushort, c_int, c_uint, c_long, c_ulong, c_longlong, c_ulonglong, c_longdouble }; + +const BitFields = packed struct { + empty: u0, + small: i7, + wide: u256, +}; + // If / else fn classify(x: i32) i32 { if (x > 10) { @@ -135,6 +164,13 @@ fn describe(value: Value) void { } } +fn inRange(number: u8) bool { + return switch (number) { + 1...3 => true, + else => false, + }; +} + // Optionals fn optional(value: ?i32) i32 { return value orelse 0; diff --git a/crates/lsh/definitions/zig.lsh b/crates/lsh/definitions/zig.lsh index 464d53b8375..c130628f745 100644 --- a/crates/lsh/definitions/zig.lsh +++ b/crates/lsh/definitions/zig.lsh @@ -4,50 +4,39 @@ pub fn zig() { until /$/ { yield other; + if /\/\/.*/ { yield comment; - } else if /\s*\\\\/ { - until /$/ {} - yield string; - - loop { - await input; - if /\s*\\\\/ { - until /$/ {} - yield string; - } else { - break; - } - } - } else if /'/ { + } else if /\\\\.*/ { + yield string; + } else if /'/ { single_quote_string(); } else if /"/ { double_quote_string(); - } else if /(?:break|continue|try|defer|else|errdefer|for|if|return|switch|unreachable|while)\>/ { + } else if /(?:break|catch|continue|defer|else|errdefer|for|if|nosuspend|orelse|resume|return|suspend|switch|try|while)\>/ { yield keyword.control; - } else if /(?:addrspace|align|allowzero|and|anyframe|anytype|asm|callconv|catch|comptime|const|enum|error|export|extern|fn|inline|linksection|noalias|noinline|nosuspend|opaque|or|orelse|packed|pub|resume|struct|suspend|test|threadlocal|union|var|volatile)\>/ { + } else if /(?:addrspace|align|allowzero|and|asm|callconv|comptime|const|enum|export|extern|fn|inline|linksection|noalias|noinline|opaque|or|packed|pub|struct|test|threadlocal|union|unreachable|var|volatile)\>/ { yield keyword.other; } else if /(?:true|false|null|undefined)\>/ { yield constant.language; - } else if /(?:bool|void|noreturn|type|anytype|anyerror|anyframe|anyopaque|isize|usize|comptime_int|comptime_float|f16|f32|f64|f80|f128)\>/ { + } else if /(?:anyerror|anyframe|anyopaque|anytype|bool|comptime_float|comptime_int|error|f16|f32|f64|f80|f128|[iu](?:\d+|size)|noreturn|type|void)\>/ { yield storage.type; - } else if /(?:c_char|c_short|c_ushort|c_int|c_uint|c_long|c_ulong|c_ulonglong|c_longlong|c_longdouble)\>/ { + } else if /c_(?:char|short|ushort|int|uint|longdouble|longlong|long|ulonglong|ulong)\>/ { yield storage.type; - } else if /(?:[iu]\d+)\>/ { - yield storage.type; - } else if /(?i:-?(?:0x[\da-f_]+|0b[01_]+|0o[0-7_]+|[\d_]+(?:\.[\d_]*)?|\.[\d_]+)(?:[eEpP][+-]?[\d_]+)?)/ { + } else if /(?i:0x[\da-f_]+(?:\.[\da-f_]+)?(?:p[+-]?[\d_]+)?|0b[01_]+|0o[0-7_]+|\d[\d_]*(?:\.[\d_]+)?(?:e[+-]?[\d_]+)?)/ { if /\w+/ { // Invalid numeric literal } else { yield constant.numeric; } - } else if /@([a-zA-Z_]\w*)/ { - yield method; + } else if /@[a-zA-Z_]\w*/ { + yield method; } else if /(\w+)\s*\(/ { yield $1 as method; } else if /\w+/ { // Gobble word chars to align the next iteration on a word boundary. } + yield other; } -} \ No newline at end of file +}