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

=begin
Multi-line comment
=end

=begin rdoc
The rest of the `=begin` line is ignored by Ruby.
=end

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

# Constants
true
false
nil
Object
String
Demo::Animal
::Kernel
MAX_SIZE = 10

# Strings
'single quotes with escape: \' \n \t \\'
"double quotes with escape: \" \n \t \\"
"interpolated: #{1 + 1} and a # that is not a comment"
`echo shell command`

# Symbols and variables
:symbol
:method_name?
attr_accessor :name, :age
@instance_var
@@class_var
$global_var
{ key: 'value' }

# 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

until true
puts "spin"
end

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

puts "even" if 42.even? and not false
puts "odd" or true

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

def self.create(name)
new(name)
end

def ==(other)
@name == other.name
end

def name=(value)
@name = value
end

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

alias old_speak speak!
undef old_speak

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

puts "hello"
Array.new(3)
greet("world")
77 changes: 77 additions & 0 deletions crates/lsh/definitions/ruby.lsh
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#[display_name = "Ruby"]
#[path = "**/*.gemspec"]
#[path = "**/*.rake"]
#[path = "**/*.rb"]
#[path = "**/*.ru"]
#[path = "**/Gemfile"]
#[path = "**/Rakefile"]
pub fn ruby() {
if /=begin\>.*/ {
loop {
yield comment;
await input;
if /=end\>.*/ {
yield comment;
break;
}
if /.*/ {}
}
return;
}

until /$/ {
yield other;

if /#.*/ {
yield comment;
} else if /'/ {
single_quote_string();
} else if /"/ {
double_quote_string();
} else if /`/ {
until /$/ {
if /\\./ {
// Escape sequences
} else if /`/ {
yield string;
break;
}
}
} else if /(?:begin|break|case|do|elsif|else|end|ensure|for|if|in|next|redo|rescue|retry|return|then|unless|until|when|while)\>/ {
yield keyword.control;
} else if /def\s+\w+\.(\w+[!?=]?)/ {
// Singleton method, as in `def self.foo`.
yield keyword.other;
yield $1 as method;
} else if /def\s+(\w+[!?=]?)/ {
yield keyword.other;
yield $1 as method;
} else if /(?:BEGIN|END|__ENCODING__|__FILE__|__LINE__|alias|and|class|defined\?|def|module|not|or|self|super|undef|yield)\>/ {
yield keyword.other;
} else if /(?:true|false|nil)\>/ {
yield constant.language;
} else if /(?i:-?(?:0x[\da-f_]+|0b[01_]+|0o[0-7_]+|[\d_]+\.[\d_]+(?:e[+-]?[\d_]+)?|[\d_]+(?:e[+-]?[\d_]+)?)r?i?)/ {
// Floats need digits on both sides of the dot, so that `1..2` and
// `1.upto(2)` don't swallow the dot.
if /\w+/ {
// Invalid numeric literal
} else {
yield constant.numeric;
}
} else if /(?:@{1,2}|\$)[A-Za-z_]\w*/ {
yield variable;
} else if /::/ {
// Scope resolution, so that `Foo::Bar` isn't mistaken for a symbol.
} else if /:[A-Za-z_]\w*[!?=]?/ {
yield constant.language;
} else if /[A-Z]\w*/ {
yield storage.type;
} 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