Skip to content
Open
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
102 changes: 102 additions & 0 deletions assets/highlighting-tests/ruby.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
# Comments
# Single-line comment

=begin
Multi-line
comment
=end

# Numbers
42
3.14
0.5
1e10
1.5e-3
0xff
0xFF
0b1010
0o77
1_000_000
3.14r
2i

# Constants
true
false
nil
Object
String

# Strings
'single quotes with escape: \' \n \t \\'
"double quotes with escape: \" \n \t \\"
`echo shell command`

# Symbols and variables
:symbol
:method_name?
@instance_var
@@class_var
$global_var

# Control flow keywords
if true
puts "yes"
elsif false
puts "no"
else
puts "maybe"
end

unless nil
puts "not nil"
end

case 42
when 1
puts "one"
else
puts "other"
end

for i in 1..3
next if i == 2
break if i == 3
end

while false
redo
end

begin
raise "oops"
rescue StandardError => e
retry
ensure
puts e
end

# Definitions and method calls
module Demo
class Animal
def initialize(name)
@name = name
end

def speak! = puts "#{@name} speaks"
end
end

alias old_speak speak!
undef old_speak

BEGIN { puts "start" }
END { puts "finish" }
defined? Demo
self
super
yield

puts "hello"
Array.new(3)
greet("world")
100 changes: 100 additions & 0 deletions crates/lsh/definitions/ruby.lsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#[display_name = "Ruby"]
#[path = "**/*.rb"]
#[path = "**/*.rake"]
#[path = "**/*.ru"]
#[path = "**/Gemfile"]
#[path = "**/Rakefile"]
pub fn ruby() {
var zero = 0;
until /$/ {
yield other;

if off == zero {
if /=begin\>/ {
loop {
yield comment;
await input;
if off == zero {
if /=end\>/ {
yield comment;
break;
}
}
}
continue;
}
}

if /#.*/ {
yield comment;
} 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 /`/ {
loop {
yield string;
if /\\./ {}
else if /`/ { yield string; break; }
await input;
}
} else if /(?:begin|break|case|class|do|else|elsif|end|ensure|for|if|in|module|next|redo|rescue|retry|return|then|unless|until|when|while)\>/ {
yield keyword.control;
} else if /def\s+(\w+[!?=]?)/ {
yield keyword.control;
yield $1 as method;
} else if /(?:BEGIN|END|alias|defined\?|self|super|undef|yield)\>/ {
yield keyword.other;
} else if /(?:true|false|nil)\>/ {
yield constant.language;
} else if /\.\.\.?/ {
// Range operator.
} else if /(?i:-?(?:0x[\da-fA-F_]+|0b[01_]+|0o[0-7_]+)r?i?)/ {
if /\w+/ {
// Invalid numeric literal
} else {
yield constant.numeric;
}
} else if /(?i:-?[\d_]+\.[\d_]+(?:e[+-]?[\d_]+)?r?i?)/ {
if /\w+/ {
// Invalid numeric literal
} else {
yield constant.numeric;
}
} else if /(?i:-?\.[\d_]+(?:e[+-]?[\d_]+)?r?i?)/ {
if /\w+/ {
// Invalid numeric literal
} else {
yield constant.numeric;
}
} else if /(?i:-?[\d_]+(?:e[+-]?[\d_]+)?r?i?)/ {
if /\w+/ {
// Invalid numeric literal
} else {
yield constant.numeric;
}
} else if /(?:@{1,2}|\$)[A-Za-z_]\w*/ {
yield variable;
} else if /:[A-Za-z_]\w*[!?=]?/ {
yield constant.language;
} else if /[A-Z]\w*/ {
yield constant.language;
} 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;
}
}