Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions assets/highlighting-tests/markdown.md
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,9 @@ export function greet(name) {
def greet(name: str) -> str:
return f"hello {name}"
```

```odin
greet :: proc(name: string) -> string {
return fmt.tprintf("hello %s", name)
}
```
144 changes: 144 additions & 0 deletions assets/highlighting-tests/odin.odin
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// Line comment
/*
* Multi-line
* comment
*/

#+feature dynamic-literals
package main

import "core:fmt"

// Numbers
Dec :: 42
Neg :: -7
Hex :: 0xCAFE_BABE
Oct :: 0o755
Bin :: 0b1010
Sep :: 1_000_000
Flt :: 3.14
Half :: .5
Exp :: 1e10
Sci :: 1.5e-3
Imag :: 2i
Quat :: 3j
HexF :: 0h3f800000
Bad :: 1abc

// Constants
yes := true
no := false
none := nil
_ = 0

// Basic types
b: bool
b32v: b32
r: rune
s: string
cs: cstring
i: int
i128v: i128
u: uint
up: uintptr
u32b: u32be
i16l: i16le
f16v: f16
f64v: f64
c128: complex128
q256: quaternion256
p: rawptr
t: typeid
a: any

// Strings and runes
char := 'a'
escaped := '\n'
quote := '\''
str := "double quotes with escapes: \" \n \t \\"
raw := `raw string
spans lines and may contain "quotes"`

Speaker :: struct #packed {
name: string `fmt:"q"`,
}

Value :: union {int, f64}

Direction :: enum {North, South}

Flags :: bit_set[Direction]

Meters :: distinct f32

Header :: bit_field u32 {
tag: u8 | 3,
}

@(deprecated = "use speak instead")
old_speak :: proc(s: Speaker) -> string {
return fmt.tprintf("%s speaks", s.name)
}

@private
compare :: proc(a, b: $T) -> bool where intrinsics.type_is_comparable(T) {
return a == b
}

foreign import kernel32 "system:kernel32.lib"

@(default_calling_convention = "std")
foreign kernel32 {
ExitProcess :: proc(code: u32) ---
}

main :: proc() {
if yes {
fmt.println("enabled")
} else when ODIN_DEBUG {
fmt.println("debug")
} else {
fmt.println("disabled")
}

for i := 0; i < 10; i += 1 {
switch {
case i == 5:
continue
case i == 8:
break
case:
fallthrough
}
}

for i in 0..<10 {}
for i in 0..=9 {}

values := [dynamic]int{1, 2, 3}
m := map[string]int{"one" = 1}
defer delete(values)
for value, index in values {
fmt.println(index, value, m["one"])
}

v: Value = 137
#partial switch _ in v {
case int:
fmt.println("int")
}

soa: #soa[4]Speaker
#unroll for i in 0..<2 {}

x := cast(int)3.14
y := transmute(u32)f32(1)
z := auto_cast x
w := m["two"] or_else 0
_, _, _, _ = x, y, z, w

#assert(size_of(u8) == 1)
context.user_index = 1
ptr := &x
ptr^ = 456
}
10 changes: 10 additions & 0 deletions crates/lsh/definitions/markdown.lsh
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,16 @@ pub fn markdown() {
if /.*/ {}
}
}
} else if /(?i:odin)/ {
loop {
await input;
if /\s*```/ {
return;
} else {
odin();
if /.*/ {}
}
}
Comment thread
santerijps marked this conversation as resolved.
} else if /(?i:py|python)/ {
loop {
await input;
Expand Down
57 changes: 57 additions & 0 deletions crates/lsh/definitions/odin.lsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
#[display_name = "Odin"]
#[path = "**/*.odin"]
pub fn odin() {
until /$/ {
yield other;

if /\/\/.*/ {
yield comment;
} else if /\/\*/ {
loop {
yield comment;
await input;
if /\*\// {
yield comment;
break;
}
}
} else if /`/ {
loop {
yield string;
if /`/ {
yield string;
break;
}
await input;
}
} else if /'/ {
single_quote_string();
} else if /"/ {
double_quote_string();
} else if /(?:break|case|continue|defer|do|else|fallthrough|for|if|in|not_in|or_break|or_continue|or_else|or_return|return|switch|when|where)\>/ {
yield keyword.control;
} else if /(?:asm|auto_cast|bit_field|bit_set|cast|context|distinct|dynamic|enum|foreign|import|map|matrix|package|proc|struct|transmute|union|using)\>/ {
yield keyword.other;
} else if /(?:true|false|nil)\>/ {
yield constant.language;
} else if /(?:any|bool|complex(?:32|64|128)|cstring|int|quaternion(?:64|128|256)|rawptr|rune|string|typeid|uintptr|uint|(?:[iu](?:8|16|32|64|128)|f(?:16|32|64)|b(?:8|16|32|64))(?:be|le)?)\>/ {
yield storage.type;
} else if /-?(?:0[xh][\da-fA-F_]+|0b[01_]+|0o[0-7_]+|\d[\d_]*\.[\d_]+|\d[\d_]*|\.\d[\d_]*)(?:[eE][+-]?[\d_]+)?[ijk]?/ {
if /\w+/ {
// Invalid numeric literal
} else {
yield constant.numeric;
}
} else if /#\+?\w+/ {
yield keyword.other;
} else if /@\w*/ {
yield storage.annotation;
} 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;
}
}
Loading