diff --git a/assets/highlighting-tests/lua.lua b/assets/highlighting-tests/lua.lua new file mode 100644 index 00000000000..0e4e1567dfd --- /dev/null +++ b/assets/highlighting-tests/lua.lua @@ -0,0 +1,100 @@ +-- Comments +-- Single-line comment + +--[[ +Multi-line comment +]] + +--[=[ +Extended multi-line comment +]=] + +-- Numbers +local n1 = 42 +local n2 = 3.14 +local n3 = 0.5 +local n4 = 1e10 +local n5 = 1.5e-3 +local n6 = 0xff +local n7 = 0xFF +local n8 = 0x1f + +-- Constants +local c1 = true +local c2 = false +local c3 = nil + +-- Strings +local s1 = 'single quotes with escape: \' \n \t \\' +local s2 = "double quotes with escape: \" \n \t \\" + +local s3 = [[ +Multi-line string +]] + +local s4 = [=[ +Extended multi-line string +]=] + +-- Control flow keywords +if true then +elseif false then +else +end + +for i = 1, 10 do + if i == 5 then + break + end +end + +while false do +end + +repeat +until true + +-- Other keywords +local x = 1 +local _y = not false and true or nil +local value = "sample" +local items = { 1, 2, 3 } +local object = { + method = function(self) + return self + end, +} + +function greet(name) + return "Hello, " .. name +end + +local function helper() + return x + n1 +end + +type Point = { + x: number, + y: number, +} + +export type Callback = (value: string) -> () + +local kind = typeof(value) + +for _, item in pairs(items) do + print(item) + continue +end + +-- Function calls +print("hello") +greet("world") +table.insert(items, 42) +object:method() + +print(n1, n2, n3, n4, n5, n6, n7, n8) +print(c1, c2, c3) +print(s1, s2, s3, s4) +print(kind) +print(helper()) diff --git a/assets/highlighting-tests/markdown.md b/assets/highlighting-tests/markdown.md index 555b182f961..8044e5a9895 100644 --- a/assets/highlighting-tests/markdown.md +++ b/assets/highlighting-tests/markdown.md @@ -80,6 +80,16 @@ export function greet(name) { } ``` +```lua +local function greet(name) + return "hello " .. name +end +``` + +```luau +export type Greeting = (name: string) -> string +``` + ```python def greet(name: str) -> str: return f"hello {name}" diff --git a/crates/lsh/definitions/lua.lsh b/crates/lsh/definitions/lua.lsh new file mode 100644 index 00000000000..dd6193c0b98 --- /dev/null +++ b/crates/lsh/definitions/lua.lsh @@ -0,0 +1,80 @@ +#[display_name = "Lua"] +#[path = "**/*.lua"] +#[path = "**/*.luau"] +pub fn lua() { + until /$/ { + yield other; + + if /--\[\[/ { + loop { + yield comment; + if /\]\]/ { + yield comment; + break; + } + await input; + } + } else if /--\[=\[/ { + loop { + yield comment; + if /\]=\]/ { + yield comment; + break; + } + await input; + } + } else if /--.*/ { + yield comment; + } else if /\[\[/ { + loop { + yield string; + if /\]\]/ { + yield string; + break; + } + await input; + } + } else if /\[=\[/ { + loop { + yield string; + if /\]=\]/ { + yield string; + break; + } + await input; + } + } else if /'/ { + until /$/ { + yield string; + if /\\./ {} + else if /'/ { yield string; break; } + await input; + } + } else if /"/ { + until /$/ { + yield string; + if /\\./ {} + else if /"/ { yield string; break; } + await input; + } + } else if /(?:break|continue|do|else|elseif|end|for|function|goto|if|in|repeat|return|then|until|while)\>/ { + yield keyword.control; + } else if /(?:and|export|local|not|or|type|typeof)\>/ { + yield keyword.other; + } else if /(?:true|false|nil)\>/ { + yield constant.language; + } else if /(?i:(?:0x[\da-f]+(?:\.[\da-f]+)?(?:p[+-]?\d+)?|-?(?:\d+(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?))/ { + if /\w+/ { + // Invalid numeric literal + } else { + yield constant.numeric; + } + } 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; + } +} diff --git a/crates/lsh/definitions/markdown.lsh b/crates/lsh/definitions/markdown.lsh index 77a005fe925..75d5c1a6cbd 100644 --- a/crates/lsh/definitions/markdown.lsh +++ b/crates/lsh/definitions/markdown.lsh @@ -60,6 +60,16 @@ pub fn markdown() { if /.*/ {} } } + } else if /(?i:lua|luau)/ { + loop { + await input; + if /\s*```/ { + return; + } else { + lua(); + if /.*/ {} + } + } } else if /(?i:py)/ { loop { await input;